Commit 0bb8d24
authored
RFC Conformance: Enforce HTTP/2 trailer field section requirements
I had Claude check the code against various RFC conformance, and it flagged below. Claude helped with the desc.
## Summary
Validate request trailers as an HTTP/2 field section and require the trailer HEADERS frame to carry `END_STREAM`.
## What was not conformant
Bandit accepted a second request HEADERS frame without `END_STREAM`, logged and ignored its fields, and continued reading DATA. It also checked only for pseudo-headers in trailers, so the normal HTTP/2 rules for lowercase names, field values, connection-specific fields, and `TE` were not applied.
[RFC 9113 section 8.1](https://www.rfc-editor.org/rfc/rfc9113.html#section-8.1) says a trailer field section must terminate the stream. It specifically requires `END_STREAM` on the terminating HEADERS frame and says a trailer section without it is a malformed request. [RFC 9113 section 8.2.1](https://www.rfc-editor.org/rfc/rfc9113.html#section-8.2.1), [RFC 9110 section 5.1](https://www.rfc-editor.org/rfc/rfc9110.html#section-5.1), and [RFC 9113 section 8.2.2](https://www.rfc-editor.org/rfc/rfc9113.html#section-8.2.2) define the field-name, field-value, and connection-specific field rules that apply to HTTP/2 field sections.
## Implementation
- Reject trailer HEADERS unless the frame carries `END_STREAM`.
- Continue rejecting pseudo-headers in trailers.
- Apply Bandit's existing lowercase-name, field-value, connection-specific field, and `TE` validators to trailers before discarding them.
- Enforce the full regular field-name token grammar and the HTTP/2 prohibition on edge SP or HTAB in trailer values.
- Validate every member of every `TE` field line, while accepting repeated `trailers` members.
- Match RFC 9113's exact connection-specific field list without rejecting unrelated extension fields by name.
- Keep the existing behavior of accepting and ignoring a valid trailer section.
- Treat a trailer field value that HPAX decodes as `nil` (an indexed static-table entry with no value) as the empty value it represents, instead of letting it crash validation (elixir-mint/hpax#27).
This is intentionally a focused change. It does not add trailer exposure to Plug and does not alter valid request-body handling.
## Tests
The protocol tests cover:
- acceptance of a valid trailer section with `END_STREAM`, including an unrelated extension field named `trailers`;
- rejection of a trailer section without `END_STREAM` with stream `PROTOCOL_ERROR`;
- rejection of a connection-specific trailer field;
- rejection when any of multiple `TE` field lines contains a value other than `trailers`;
- rejection of invalid trailer field names; and
- rejection of CR and edge whitespace in trailer field values; and
- acceptance of a trailer field encoded as an indexed static-table entry with no value.
Run:
```console
mix test test/bandit/http2/protocol_test.exs
```
Verified against Bandit `main` at `b084b37` with Erlang/OTP 27.3 and Elixir 1.18.4:
- `mix format --check-formatted`
- `MIX_ENV=test mix compile --warnings-as-errors`
- Full non-slow suite: 821 tests pass (the suite's one IPv6 server binding test needs an IPv6-capable host)
- `mix credo --strict` and `mix dialyzer` pass on the combined tree of all nineteen prepared Bandit changes
- h2spec 2.6.0 passes in full on the combined tree
- HTTP/2 protocol suite: 184 tests pass1 parent b084b37 commit 0bb8d24
2 files changed
Lines changed: 199 additions & 6 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
219 | 219 | | |
220 | 220 | | |
221 | 221 | | |
222 | | - | |
| 222 | + | |
223 | 223 | | |
224 | 224 | | |
225 | 225 | | |
226 | 226 | | |
227 | 227 | | |
228 | 228 | | |
229 | 229 | | |
230 | | - | |
| 230 | + | |
| 231 | + | |
| 232 | + | |
| 233 | + | |
| 234 | + | |
| 235 | + | |
| 236 | + | |
| 237 | + | |
| 238 | + | |
| 239 | + | |
| 240 | + | |
231 | 241 | | |
232 | 242 | | |
233 | 243 | | |
| |||
266 | 276 | | |
267 | 277 | | |
268 | 278 | | |
269 | | - | |
270 | 279 | | |
271 | 280 | | |
272 | 281 | | |
| |||
297 | 306 | | |
298 | 307 | | |
299 | 308 | | |
| 309 | + | |
| 310 | + | |
| 311 | + | |
| 312 | + | |
| 313 | + | |
| 314 | + | |
| 315 | + | |
| 316 | + | |
| 317 | + | |
| 318 | + | |
| 319 | + | |
| 320 | + | |
| 321 | + | |
| 322 | + | |
| 323 | + | |
| 324 | + | |
| 325 | + | |
| 326 | + | |
| 327 | + | |
| 328 | + | |
| 329 | + | |
| 330 | + | |
| 331 | + | |
| 332 | + | |
| 333 | + | |
| 334 | + | |
| 335 | + | |
| 336 | + | |
| 337 | + | |
| 338 | + | |
| 339 | + | |
| 340 | + | |
| 341 | + | |
| 342 | + | |
| 343 | + | |
| 344 | + | |
| 345 | + | |
| 346 | + | |
| 347 | + | |
| 348 | + | |
| 349 | + | |
| 350 | + | |
| 351 | + | |
| 352 | + | |
| 353 | + | |
| 354 | + | |
| 355 | + | |
| 356 | + | |
| 357 | + | |
| 358 | + | |
300 | 359 | | |
301 | 360 | | |
302 | 361 | | |
| |||
319 | 378 | | |
320 | 379 | | |
321 | 380 | | |
| 381 | + | |
322 | 382 | | |
323 | 383 | | |
324 | 384 | | |
| |||
560 | 620 | | |
561 | 621 | | |
562 | 622 | | |
563 | | - | |
564 | | - | |
| 623 | + | |
| 624 | + | |
| 625 | + | |
565 | 626 | | |
566 | 627 | | |
567 | 628 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
2073 | 2073 | | |
2074 | 2074 | | |
2075 | 2075 | | |
2076 | | - | |
| 2076 | + | |
| 2077 | + | |
| 2078 | + | |
2077 | 2079 | | |
2078 | 2080 | | |
2079 | 2081 | | |
| |||
2084 | 2086 | | |
2085 | 2087 | | |
2086 | 2088 | | |
| 2089 | + | |
| 2090 | + | |
| 2091 | + | |
| 2092 | + | |
| 2093 | + | |
| 2094 | + | |
| 2095 | + | |
| 2096 | + | |
| 2097 | + | |
| 2098 | + | |
| 2099 | + | |
| 2100 | + | |
| 2101 | + | |
| 2102 | + | |
| 2103 | + | |
| 2104 | + | |
| 2105 | + | |
| 2106 | + | |
| 2107 | + | |
| 2108 | + | |
| 2109 | + | |
| 2110 | + | |
| 2111 | + | |
| 2112 | + | |
| 2113 | + | |
| 2114 | + | |
| 2115 | + | |
| 2116 | + | |
| 2117 | + | |
| 2118 | + | |
| 2119 | + | |
| 2120 | + | |
| 2121 | + | |
| 2122 | + | |
| 2123 | + | |
| 2124 | + | |
| 2125 | + | |
| 2126 | + | |
| 2127 | + | |
| 2128 | + | |
| 2129 | + | |
| 2130 | + | |
| 2131 | + | |
| 2132 | + | |
| 2133 | + | |
| 2134 | + | |
| 2135 | + | |
| 2136 | + | |
| 2137 | + | |
| 2138 | + | |
| 2139 | + | |
| 2140 | + | |
| 2141 | + | |
| 2142 | + | |
| 2143 | + | |
| 2144 | + | |
| 2145 | + | |
| 2146 | + | |
| 2147 | + | |
| 2148 | + | |
| 2149 | + | |
| 2150 | + | |
| 2151 | + | |
| 2152 | + | |
| 2153 | + | |
| 2154 | + | |
| 2155 | + | |
| 2156 | + | |
| 2157 | + | |
| 2158 | + | |
| 2159 | + | |
| 2160 | + | |
| 2161 | + | |
| 2162 | + | |
| 2163 | + | |
| 2164 | + | |
| 2165 | + | |
| 2166 | + | |
| 2167 | + | |
| 2168 | + | |
| 2169 | + | |
| 2170 | + | |
| 2171 | + | |
| 2172 | + | |
| 2173 | + | |
| 2174 | + | |
| 2175 | + | |
| 2176 | + | |
| 2177 | + | |
| 2178 | + | |
| 2179 | + | |
| 2180 | + | |
| 2181 | + | |
| 2182 | + | |
| 2183 | + | |
| 2184 | + | |
| 2185 | + | |
| 2186 | + | |
| 2187 | + | |
| 2188 | + | |
| 2189 | + | |
| 2190 | + | |
| 2191 | + | |
| 2192 | + | |
| 2193 | + | |
| 2194 | + | |
| 2195 | + | |
| 2196 | + | |
| 2197 | + | |
| 2198 | + | |
| 2199 | + | |
| 2200 | + | |
| 2201 | + | |
| 2202 | + | |
| 2203 | + | |
| 2204 | + | |
| 2205 | + | |
| 2206 | + | |
| 2207 | + | |
| 2208 | + | |
| 2209 | + | |
| 2210 | + | |
| 2211 | + | |
| 2212 | + | |
| 2213 | + | |
| 2214 | + | |
| 2215 | + | |
| 2216 | + | |
| 2217 | + | |
| 2218 | + | |
2087 | 2219 | | |
2088 | 2220 | | |
2089 | 2221 | | |
| |||
0 commit comments