Skip to content

fix(agentex): bump h2 4.3.0 -> 4.4.1 (CVE-2026-71554) - #397

Open
scale-prodsec[bot] wants to merge 1 commit into
mainfrom
security-bot/gfdvr-23782-trivy-remediate-h2430-vulnerabilities
Open

fix(agentex): bump h2 4.3.0 -> 4.4.1 (CVE-2026-71554)#397
scale-prodsec[bot] wants to merge 1 commit into
mainfrom
security-bot/gfdvr-23782-trivy-remediate-h2430-vulnerabilities

Conversation

@scale-prodsec

@scale-prodsec scale-prodsec Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Summary

Bumps h2 4.3.0 -> 4.4.1 in the workspace uv.lock to remediate CVE-2026-71554.

Linear: GFDVR-23782 (child: GFDVR-23783)

Package h2 (python-pkg, transitive via httpx[http2])
Version 4.3.0 -> 4.4.1
CVE CVE-2026-71554 (MEDIUM, CWE-444) — GHSA-6hr6-w5qg-qmwg
Surface uv.lock (root workspace lock consumed by agentex/Dockerfile)
Image golden/agentex@sha256:d34c1ea2…

The vulnerability

h2 <= 4.4.0 accepts request header blocks containing more than one Host header and forwards every one to the consuming application. Where a consumer downgrades HTTP/2 to HTTP/1.1, the resulting request carries two Host header lines — a request-smuggling primitive (CWE-444). Fixed in 4.4.1 by 292a408, which raises ProtocolError on duplicate Host headers on both the receive and send paths.

Changes

uv.lock only — 1 file, 6 insertions / 6 deletions:

  • h2 4.3.0 -> 4.4.1
  • hpack 4.1.0 -> 4.2.0 — required closure member; h2 4.4.1 declares hpack<5,>=4.2 (4.3.0 declared >=4.1)

No manifest change: h2 is transitive and no pyproject.toml declares it. Re-locked with the package-targeted uv lock --upgrade-package h2; lock revision = 3 preserved (local uv 0.7.22 rewrites it to 2, so uv@0.8.17 was used). All resolved URLs remain on files.pythonhosted.org; no registry flip. No application code touched.

Behavior-contract review

h2 4.4.0 carries backward-incompatible API changes, so both crossed versions were reviewed against the actual consumer (httpcore 1.0.9, pinned):

4.4.0/4.4.1 change Impact here
Duplicate Host -> ProtocolError (the fix) None. httpcore/_async/http2.py:243-246 strips b"host" and maps it to :authority before send_headers, so a duplicate can't be constructed on this path.
Duplicate/RFC9110 content-length -> ProtocolError None. httpcore never passes content-length through to h2.
Stream.end_stream() raises NoSuchStreamError/StreamClosedError instead of KeyError None. httpcore does not catch KeyError around end_stream; it only catches NoAvailableStreamIDError.
CONNECT pseudo-header validation (RFC 9113 s8.3 / RFC 8441 s4) None. No CONNECT or WebSocket usage in this service — only ordinary requests and client.stream().
Python 3.9 / PyPy 3.9 support dropped None. Workspace is requires-python = "==3.12.*".
Events converted to dataclasses None (already in 4.3.0, the current version).

HTTP/2 is live here (http2=True in adapters/http/adapter_httpx.py and utils/cached_httpx_client.py), so this was verified by execution rather than inspection alone. Separately, both header-forwarding paths in this repo (agent_acp_service.py HOP_BY_HOP_HEADERS, middleware_utils.py DROP_HEADERS) already drop host, so no Host header is ever forwarded downstream.

Upstream tracker swept for regression / breaking / 4.4.0 / 4.4.1 — no open issues against either release.

Verification

  • Advisory gate — OSV via bot.version_gate: h2 4.4.1 has zero known vulnerabilities.
  • Parent range — httpx 0.28.1 declares h2<5,>=3; target is inside it, no parent co-upgrade needed.
  • Lock integrityuv lock --check clean; revision = 3 preserved.
  • Dockerfile production pathuv export --frozen --no-dev --no-emit-project --package agentex-backend resolves h2==4.4.1, hpack==4.2.0.
  • Frozen installuv run --frozen --group test --package agentex-backend installs cleanly (189 packages).
  • Runtime smoke (h2 4.4.1 + httpx 0.28.1 + httpcore 1.0.9): httpx.AsyncClient(http2=True) constructs; the httpcore-style host -> :authority send path succeeds with no ProtocolError; a genuine duplicate-Host block now raises ProtocolError: Request header block has multiple Host headers. — confirming the fix is present and enforced.
  • Unit suitepytest agentex/tests/unit: 518 passed / 187 errors, byte-identical to the untouched-baseline run on the same environment. All 187 errors are pre-existing testcontainers/Docker-daemon setup failures in this sandbox, unrelated to this change.

h2 4.3.0 accepts request header blocks containing multiple Host headers
and forwards them all to the consuming application. Where a consumer
downgrades HTTP/2 to HTTP/1.1 the resulting request carries two Host
header lines, a request smuggling primitive (CWE-444).

h2 4.4.1 rejects duplicate Host headers with a ProtocolError on both the
receive and send paths.

Transitive via httpx[http2] (httpx 0.28.1 declares h2<5,>=3, so the
target is inside the parent range). hpack 4.1.0 -> 4.2.0 comes along
because h2 4.4.1 requires hpack<5,>=4.2.
@scale-prodsec
scale-prodsec Bot requested a review from a team as a code owner August 7, 2026 03:01
@greptile-apps

greptile-apps Bot commented Aug 7, 2026

Copy link
Copy Markdown

No reviewable files after applying ignore patterns.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants