CVE-2026-45409 — idna 3.11 → 3.15
Context
pip-audit --strict --desc flags idna 3.11 as vulnerable to CVE-2026-45409 (DoS via idna.encode() on crafted long inputs containing characters like "٠" or "・" * N + "漢"). Same root issue as CVE-2024-3651; the 2024 patch was incomplete. Fixed in idna 3.14 (primary path) and 3.15 (alternate paths). idna is a pure transitive dependency here — pulled in by requests, httpx, anyio, and others — so no project code calls idna.encode() directly. The risk is downstream HTTP clients passing untrusted hostnames into the resolver.
Goal
Lift the project’s idna floor to >= 3.15 across all instances and prove the regression cannot recur via a lock refresh.
Approach
Single-commit security PR off main:
- Add
"idna>=3.15"to[project].dependenciesinpyproject.tomlwith an inline comment naming the CVE. This makes the security floor explicit and visible to anyone reading the manifest, and survives any futureuv lock --upgraderebuild without the--upgrade-package idnaargument. uv lock --upgrade-package idnato regenerateuv.lockwith idna 3.15+.- Verify with
uv run pip-audit --strict --desc(clean) anduv run pytest(green).
Rejected alternatives:
- Lock-only bump: smallest diff, but a future
uv lockrebuild could in theory float idna back if a parent dep’s range narrows. Weakest guarantee for downstream instances. [tool.uv].constraint-dependencies: enforces the floor without making idna a direct dep, but the syntax is less common in this repo and the floor is less visible to a casual reader ofpyproject.toml.
Scope (and what is out of scope)
In scope: bump idna; verify; PR to main.
Out of scope: adding pip-audit to CI; bumping other deps; updating the open feat/observability-stack PR. Once the fix lands on main, feat/observability-stack will be updated via a follow-up merge from main (not a rebase — that branch is 30 commits ahead and has an active PR whose review state should not be invalidated).
Risk
Very low. idna is parsing-only and the 3.11 → 3.15 changelog is bugfix-only. Full test suite must remain green; any failure would point at a hashing/lock-resolution issue rather than behavioral change.