Skip to content

Mitigate HTTP/2 HPACK "bomb" amplification (decoded list-size + reassembly caps)#830

Merged
ademar merged 3 commits into
masterfrom
copilot/investigate-http2-security-vulnerability
Jun 3, 2026
Merged

Mitigate HTTP/2 HPACK "bomb" amplification (decoded list-size + reassembly caps)#830
ademar merged 3 commits into
masterfrom
copilot/investigate-http2-security-vulnerability

Conversation

Copilot AI commented Jun 3, 2026

Copy link
Copy Markdown
Contributor

Suave's HTTP/2 stack had no upper bound on either the decoded HPACK header list or the cumulative HEADERS+CONTINUATION reassembly buffer, so a peer could expand a few bytes on the wire (repeated indexed-references into a populated dynamic table, or an unbounded CONTINUATION chain) into arbitrary server-side memory — the attack described in the HPACK bomb writeup.

Changes

  • Hpack.fs — bounded decoder. New decodeHeaderBounded : DynamicTable -> int option -> byte[] -> HeaderList and underlying decodeSimpleBounded track RFC 7541 §4.1 size (name + value + 32) per header during decoding and raise the new HpackHeaderListTooLargeException the moment the running total exceeds the cap, so we don't finish materialising the giant list. Legacy decodeHeader/decodeSimple remain as thin None wrappers.

  • Http2.fs — defaults + enforcement.

    • defaultMaxHeaderListSize = 32768 and defaultMaxHeaderBlockReassemblyBytes = 32768 constants.
    • Per-connection localSettings initialised with maxHeaderBlockSize = Some defaultMaxHeaderListSize; both the h2c-upgrade and prior-knowledge server prefaces now emit Settings(false, localSettings) instead of defaultSetting, advertising SETTINGS_MAX_HEADER_LIST_SIZE to peers.
    • handleFrame rejects an initial HEADERS fragment or a CONTINUATION that would push the reassembly buffer past the compressed cap.
    • completeHeaderBlock calls decodeHeaderBounded with localSettings.maxHeaderBlockSize and maps HpackHeaderListTooLargeException to a connection-level abort.
    • All trips send GOAWAY(ENHANCE_YOUR_CALM); stream-level reset is unsafe because the HPACK dynamic table may already be partially mutated.
  • Suave.Tests/Http2.fs — regression test. Plants a 200-byte value in the dynamic table via a literal-with-incremental-indexing frame, then replays it with a single 0xBE indexed reference, asserting decodeHeaderBounded aborts under a tight cap and decodes normally under a generous cap / None.

Notes for reviewers

  • 32 KiB matches the de-facto default of Tomcat/IIS and is well above any plausible legitimate request; configurable wiring to SuaveConfig is intentionally out of scope here.
  • The compressed reassembly cap is deliberately equal to the decoded cap — HPACK output is never smaller than the input, so this is a safe joint bound and leaves no separate code path to widen later.
  • defaultSetting is unchanged, so the existing "SETTINGS encode only emits explicitly-set entries" tests and any external callers that compare against it keep working.

Copilot AI linked an issue Jun 3, 2026 that may be closed by this pull request
Copilot AI changed the title [WIP] Investigate HTTP/2 bomb vulnerability and assess HPACK implementation Mitigate HTTP/2 HPACK "bomb" amplification (decoded list-size + reassembly caps) Jun 3, 2026
Copilot finished work on behalf of ademar June 3, 2026 18:30
Copilot AI requested a review from ademar June 3, 2026 18:30
@ademar ademar marked this pull request as ready for review June 3, 2026 18:49
@ademar ademar merged commit a786bfe into master Jun 3, 2026
2 checks passed
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.

Investigate possible HTTP/2 security vulnerability

2 participants