Skip to content

Validate HTTP/2 DATA, padding, SETTINGS and extension frames - #512

Open
ericmj wants to merge 3 commits into
mainfrom
http2-frame-validation
Open

ericmj wants to merge 3 commits into
mainfrom
http2-frame-validation

Conversation

@ericmj

@ericmj ericmj commented Sep 24, 2026 •

Copy link
Copy Markdown
Member

Frame-level validation fixes for Mint.HTTP2. Each commit is one fix with its own tests, so this is meant to be rebase-merged rather than squashed.

  • Count the Pad Length byte of padded DATA frames against the receive windows. RFC 9113 §6.1 flow-controls the whole payload, but only the data and padding were counted, so the server's view of the window drifted by one byte per padded frame and the client stopped refilling it.
  • Reset the stream with PROTOCOL_ERROR when DATA arrives before the response HEADERS, including after an interim response. It used to be delivered as {:data, ref, _} with no :status before it (RFC 9113 §8.1).
  • Reject padded DATA, HEADERS and PUSH_PROMISE frames with no Pad Length byte and SETTINGS ACK frames with a payload as FRAME_SIZE_ERROR, and SETTINGS_ENABLE_PUSH values other than 0, or 1 from a server, as PROTOCOL_ERROR (RFC 9113 §6.1, §6.5, §6.5.2).
  • Accept PRIORITY frames on idle streams, which RFC 9113 §5.1 allows and which used to be a connection error on client stream IDs not opened yet.
  • Treat an extension frame in the middle of a header block as a PROTOCOL_ERROR connection error instead of ignoring it (RFC 9113 §5.5).

Every commit's tests were run without its fix applied and fail there.

…order

The flow-control accounting for a padded DATA frame counted the data
and the padding but not the Pad Length byte, while RFC 9113 6.1 says the
whole payload is flow controlled. The server's view of the receive
window drifted by one byte per padded frame, and once the drift passed
the WINDOW_UPDATE threshold the server saw an empty window that the
client never refilled.

A DATA frame arriving before the response HEADERS frame was delivered
as a :data response with no preceding :status. RFC 9113 8.1 defines a
response as HEADERS followed by DATA, and 8.1.1 makes a malformed
response a stream error, so the stream is now reset with PROTOCOL_ERROR
and the caller receives an error response.
@coveralls

coveralls commented Sep 24, 2026 •

Copy link
Copy Markdown

Coverage Report for CI Build 5136294

Coverage increased (+0.1%) to 88.833%

Details

  • Coverage increased (+0.1%) from the base build.
  • Patch coverage: 1 uncovered change across 1 file (38 of 39 lines covered, 97.44%).
  • No coverage regressions found.

Uncovered Changes

File Changed Covered %
lib/mint/http2/frame.ex 11 10 90.91%
Total (2 files) 39 38 97.44%

Coverage Regressions

No coverage regressions found.


Coverage Stats

Coverage Status
Relevant Lines: 1800
Covered Lines: 1599
Line Coverage: 88.83%
Coverage Strength: 548.21 hits per line

💛 - Coveralls

A DATA, HEADERS or PUSH_PROMISE frame with the PADDED flag and an empty
payload has no Pad Length field and is a FRAME_SIZE_ERROR (RFC 9113 6.1),
a SETTINGS frame with the ACK flag and a payload is a FRAME_SIZE_ERROR
(RFC 9113 6.5), and SETTINGS_ENABLE_PUSH is only valid as 0 or 1 and must
not be set to 1 by a server (RFC 9113 6.5.2). All three used to be
accepted.
…ames in header blocks

PRIORITY frames on a client stream ID the client hadn't opened yet were
treated as a connection error, but RFC 9113 5.1 allows PRIORITY on idle
streams. They are now accepted.

Extension frames received in the middle of a header block were ignored
instead of being treated as the PROTOCOL_ERROR RFC 9113 5.5 requires.
@ericmj
ericmj force-pushed the http2-frame-validation branch from 295d132 to 5136294 Compare September 24, 2026 11:13
@ericmj ericmj changed the title Validate HTTP/2 frames against flow control, framing and stream state rules Validate HTTP/2 DATA, padding, SETTINGS and extension frames Sep 24, 2026
@ericmj
ericmj marked this pull request as ready for review September 24, 2026 11:15
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.

2 participants