Skip to content

fix(l7): reject requests with both CL and TE headers in inference parser (CWE-444)#671

Open
latenighthackathon wants to merge 2 commits intoNVIDIA:mainfrom
latenighthackathon:fix/inference-cl-te-rejection
Open

fix(l7): reject requests with both CL and TE headers in inference parser (CWE-444)#671
latenighthackathon wants to merge 2 commits intoNVIDIA:mainfrom
latenighthackathon:fix/inference-cl-te-rejection

Conversation

@latenighthackathon
Copy link
Copy Markdown
Contributor

@latenighthackathon latenighthackathon commented Mar 30, 2026

Summary

The CL/TE desynchronisation guard added in #663 for the REST path was not applied to the inference request parser. A request containing both Content-Length and Transfer-Encoding headers is silently accepted by inference.rs, with Content-Length ignored in favour of chunked transfer-encoding. This enables HTTP request smuggling if an upstream server interprets the request via Content-Length instead (CWE-444, RFC 7230 Section 3.3.3).

Related Issue

Closes #670

Follow-up to #663 / #637 — same vulnerability class, sister parser.

Changes

  • Added CL+TE dual-header rejection check in try_parse_http_request() after header parsing loop, returning ParseResult::Invalid when both is_chunked and has_content_length are true.
  • Added reject_dual_content_length_and_transfer_encoding and reject_dual_transfer_encoding_and_content_length tests mirroring SEC-009 coverage in rest.rs.
  • Added te_substring_not_chunked test verifying partial TE tokens like chunkedx are not treated as chunked.
  • Aligned error message casing with rest.rs convention ("Request contains..." instead of "request contains...").

Testing

  • mise run pre-commit passes (no local Rust toolchain)
  • Unit tests added/updated

Executed:

  • Verified all three new tests exercise the intended code paths by tracing through try_parse_http_request() logic
  • Confirmed existing tests (duplicate CL, non-numeric CL, chunked parsing) are unaffected by the new guard placement
  • Checked line lengths against existing test patterns in inference.rs (byte string literals up to 152 chars are accepted by cargo fmt)

Checklist

  • Follows Conventional Commits
  • Commits are signed off (DCO)
  • Architecture docs updated (if applicable)

…ser (CWE-444)

The CL/TE desynchronisation guard added in NVIDIA#663 for the REST path was
not applied to the inference request parser.  A request containing both
Content-Length and Transfer-Encoding headers could be interpreted
differently by the proxy and the upstream server, enabling HTTP request
smuggling (CWE-444, RFC 7230 Section 3.3.3).

Add the same rejection check and two tests mirroring the REST parser
coverage.

Signed-off-by: latenighthackathon <latenighthackathon@users.noreply.github.com>
@latenighthackathon latenighthackathon requested a review from a team as a code owner March 30, 2026 05:03
Align the CL+TE rejection message with rest.rs casing ("Request"
instead of "request") and add a te_substring_not_chunked test
verifying that partial Transfer-Encoding tokens like "chunkedx"
are not mistakenly treated as chunked.

Signed-off-by: latenighthackathon <latenighthackathon@users.noreply.github.com>
@latenighthackathon
Copy link
Copy Markdown
Contributor Author

Self-review follow-up in b2b3d61:

  1. Capitalised error message"Request contains both..." now matches the casing convention in rest.rs (line 267) for the equivalent guard.
  2. Added te_substring_not_chunked test — verifies that a partial Transfer-Encoding value like chunkedx is not mistakenly treated as chunked. Mirrors the same test in rest.rs (line 758). The inference parser already handles this correctly via .eq_ignore_ascii_case("chunked") on split values, but there was no test coverage.

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.

fix(l7): inference parser missing CL+TE dual-header rejection (CWE-444)

1 participant