From b083985b1d5c8fc456c60738d070dae9087661f7 Mon Sep 17 00:00:00 2001 From: James Williams <29534093+williajm@users.noreply.github.com> Date: Tue, 12 May 2026 20:55:11 +0100 Subject: [PATCH 1/3] =?UTF-8?q?security:=20Bump=20urllib3=202.6.3=20?= =?UTF-8?q?=E2=86=92=202.7.0=20(CVE-2026-44431)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit GHSA-qccp-gfcp-xxvc: urllib3 prior to 2.7.0 forwards sensitive headers (Authorization, Cookie, Proxy-Authorization) across origins when following redirects via the low-level ProxyManager.connection_from_url().urlopen() API. Pin urllib3>=2.7.0 directly in pyproject.toml so the constraint survives future resolutions even though it only enters via transitive deps (docker, requests). Co-Authored-By: Claude Opus 4.7 (1M context) --- pyproject.toml | 1 + uv.lock | 11 ++++++++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index bc0ae5b..2cd142c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -50,6 +50,7 @@ dependencies = [ "httpx>=0.28.1", "typer>=0.24.1", "python-multipart>=0.0.26", # CVE-2026-24486 / CVE-2026-40347: Path traversal fix + "urllib3>=2.7.0", # CVE-2026-44431 / GHSA-qccp-gfcp-xxvc: Sensitive headers forwarded across origins in proxied low-level redirects ] [project.optional-dependencies] diff --git a/uv.lock b/uv.lock index c39a415..860039c 100644 --- a/uv.lock +++ b/uv.lock @@ -2,6 +2,9 @@ version = 1 revision = 3 requires-python = ">=3.11" +[options] +exclude-newer = "2026-05-09T00:00:00Z" + [[package]] name = "aiofile" version = "3.9.0" @@ -994,6 +997,7 @@ dependencies = [ { name = "secure" }, { name = "starlette" }, { name = "typer" }, + { name = "urllib3" }, { name = "uvicorn" }, ] @@ -1057,6 +1061,7 @@ requires-dist = [ { name = "starlette", specifier = ">=0.52.1" }, { name = "typer", specifier = ">=0.24.1" }, { name = "types-docker", marker = "extra == 'dev'", specifier = ">=7.1.0.20260109" }, + { name = "urllib3", specifier = ">=2.7.0" }, { name = "uvicorn", specifier = ">=0.42.0" }, ] provides-extras = ["dev"] @@ -1981,11 +1986,11 @@ wheels = [ [[package]] name = "urllib3" -version = "2.6.3" +version = "2.7.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/c7/24/5f1b3bdffd70275f6661c76461e25f024d5a38a46f04aaca912426a2b1d3/urllib3-2.6.3.tar.gz", hash = "sha256:1b62b6884944a57dbe321509ab94fd4d3b307075e0c2eae991ac71ee15ad38ed", size = 435556, upload-time = "2026-01-07T16:24:43.925Z" } +sdist = { url = "https://files.pythonhosted.org/packages/53/0c/06f8b233b8fd13b9e5ee11424ef85419ba0d8ba0b3138bf360be2ff56953/urllib3-2.7.0.tar.gz", hash = "sha256:231e0ec3b63ceb14667c67be60f2f2c40a518cb38b03af60abc813da26505f4c", size = 433602, upload-time = "2026-05-07T16:13:18.596Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/39/08/aaaad47bc4e9dc8c725e68f9d04865dbcb2052843ff09c97b08904852d84/urllib3-2.6.3-py3-none-any.whl", hash = "sha256:bf272323e553dfb2e87d9bfd225ca7b0f467b919d7bbd355436d3fd37cb0acd4", size = 131584, upload-time = "2026-01-07T16:24:42.685Z" }, + { url = "https://files.pythonhosted.org/packages/7f/3e/5db95bcf282c52709639744ca2a8b149baccf648e39c8cc87553df9eae0c/urllib3-2.7.0-py3-none-any.whl", hash = "sha256:9fb4c81ebbb1ce9531cce37674bbc6f1360472bc18ca9a553ede278ef7276897", size = 131087, upload-time = "2026-05-07T16:13:17.151Z" }, ] [[package]] From dc7054625591a2af13bfac27d3838cb72d8e762a Mon Sep 17 00:00:00 2001 From: James Williams <29534093+williajm@users.noreply.github.com> Date: Tue, 12 May 2026 21:00:55 +0100 Subject: [PATCH 2/3] fix: Remove exclude-newer block from lock so CI --locked sync works Previous commit regenerated the lock with --exclude-newer, which embedded [options] exclude-newer in the lockfile. CI runs uv sync --all-extras --locked without that flag, and uv rejected the lock as modified (same failure mode previously hit in mcp_kafka #43). Regenerated with UV_EXCLUDE_NEWER unset. Package versions unchanged (urllib3 2.7.0). Co-Authored-By: Claude Opus 4.7 (1M context) --- uv.lock | 3 --- 1 file changed, 3 deletions(-) diff --git a/uv.lock b/uv.lock index 860039c..62f2be8 100644 --- a/uv.lock +++ b/uv.lock @@ -2,9 +2,6 @@ version = 1 revision = 3 requires-python = ">=3.11" -[options] -exclude-newer = "2026-05-09T00:00:00Z" - [[package]] name = "aiofile" version = "3.9.0" From e9886b9b658d5629d68fe449b62a2c060646a10a Mon Sep 17 00:00:00 2001 From: James Williams <29534093+williajm@users.noreply.github.com> Date: Tue, 12 May 2026 21:02:40 +0100 Subject: [PATCH 3/3] =?UTF-8?q?security:=20Also=20bump=20python-multipart?= =?UTF-8?q?=200.0.26=20=E2=86=92=200.0.28=20(GHSA-pp6c-gr5w-3c5g)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit GHSA-pp6c-gr5w-3c5g (high): unbounded part-header parsing in python-multipart allows a DoS via crafted multipart bodies. Fixed in 0.0.27. Also update the urllib3 pin comment to call out GHSA-mf9v-mfxr-j63j (decompression-bomb safeguard bypass), which is also fixed by the 2.7.0 bump this PR already makes. Co-Authored-By: Claude Opus 4.7 (1M context) --- pyproject.toml | 4 ++-- uv.lock | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 2cd142c..daedebf 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -49,8 +49,8 @@ dependencies = [ "authlib>=1.6.11", # GHSA-jj8c-mmj3-mmgv "httpx>=0.28.1", "typer>=0.24.1", - "python-multipart>=0.0.26", # CVE-2026-24486 / CVE-2026-40347: Path traversal fix - "urllib3>=2.7.0", # CVE-2026-44431 / GHSA-qccp-gfcp-xxvc: Sensitive headers forwarded across origins in proxied low-level redirects + "python-multipart>=0.0.27", # CVE-2026-24486 / CVE-2026-40347 / GHSA-pp6c-gr5w-3c5g: Path traversal + unbounded part-header DoS + "urllib3>=2.7.0", # GHSA-qccp-gfcp-xxvc + GHSA-mf9v-mfxr-j63j: cross-origin header leak in proxied redirects + decompression-bomb safeguard bypass ] [project.optional-dependencies] diff --git a/uv.lock b/uv.lock index 62f2be8..7507bac 100644 --- a/uv.lock +++ b/uv.lock @@ -1052,7 +1052,7 @@ requires-dist = [ { name = "pytest-asyncio", marker = "extra == 'dev'", specifier = ">=1.3.0" }, { name = "pytest-cov", marker = "extra == 'dev'", specifier = ">=7.0.0" }, { name = "pytest-docker", marker = "extra == 'dev'", specifier = ">=3.2.5" }, - { name = "python-multipart", specifier = ">=0.0.26" }, + { name = "python-multipart", specifier = ">=0.0.27" }, { name = "ruff", marker = "extra == 'dev'", specifier = ">=0.15.7" }, { name = "secure", specifier = ">=1.0.1" }, { name = "starlette", specifier = ">=0.52.1" }, @@ -1482,11 +1482,11 @@ wheels = [ [[package]] name = "python-multipart" -version = "0.0.26" +version = "0.0.28" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/88/71/b145a380824a960ebd60e1014256dbb7d2253f2316ff2d73dfd8928ec2c3/python_multipart-0.0.26.tar.gz", hash = "sha256:08fadc45918cd615e26846437f50c5d6d23304da32c341f289a617127b081f17", size = 43501, upload-time = "2026-04-10T14:09:59.473Z" } +sdist = { url = "https://files.pythonhosted.org/packages/82/54/a85eb421fbdd5007bc5af39d0f4ed9fa609e0fedbfdc2adcf0b34526870e/python_multipart-0.0.28.tar.gz", hash = "sha256:8550da197eac0f7ab748961fc9509b999fa2662ea25cef857f05249f6893c0f8", size = 45314, upload-time = "2026-05-10T11:05:16.596Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/9a/22/f1925cdda983ab66fc8ec6ec8014b959262747e58bdca26a4e3d1da29d56/python_multipart-0.0.26-py3-none-any.whl", hash = "sha256:c0b169f8c4484c13b0dcf2ef0ec3a4adb255c4b7d18d8e420477d2b1dd03f185", size = 28847, upload-time = "2026-04-10T14:09:58.131Z" }, + { url = "https://files.pythonhosted.org/packages/f3/a2/43bbc5860b5034e2af4ef99a0e04d726ff329c43e192ef3abaa8d7ecfce5/python_multipart-0.0.28-py3-none-any.whl", hash = "sha256:10faac07eb966c3f48dc415f9dee46c04cb10d58d30a35677db8027c825ed9b6", size = 29438, upload-time = "2026-05-10T11:05:15.052Z" }, ] [[package]]