Skip to content

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

@latenighthackathon

Description

@latenighthackathon

Agent Diagnostic

  • Loaded the full OpenShell repository and read crates/openshell-sandbox/src/l7/inference.rs and crates/openshell-sandbox/src/l7/rest.rs
  • Compared CWE-444 mitigations between the two parsers after PR fix(l7): reject duplicate Content-Length headers to prevent request smuggling (CWE-444) #663 merged
  • Found that rest.rs rejects requests with both Content-Length and Transfer-Encoding headers (lines 265-269), but inference.rs does not
  • inference.rs silently prioritises Transfer-Encoding: chunked and ignores the Content-Length header when both are present (lines 167-178)
  • Confirmed the gap is not covered by any test — no reject_dual_* test exists in inference.rs, unlike rest.rs which has two

Description

PR #663 added CWE-444 mitigations to the L7 REST proxy path (rest.rs), including rejection of requests containing both Content-Length and Transfer-Encoding headers. The same guard was not applied to the inference request parser (inference.rs).

When both headers are present, the inference parser silently uses chunked transfer-encoding and ignores Content-Length. If an upstream server interprets the request via Content-Length instead, the resulting desynchronisation enables HTTP request smuggling (CWE-444, RFC 7230 Section 3.3.3).

Expected: Requests with both CL and TE headers should be rejected with a 400 Bad Request, matching the REST parser behaviour.

Actual: Requests with both headers are accepted; CL is silently ignored in favour of TE.

Reproduction Steps

  1. Read crates/openshell-sandbox/src/l7/inference.rs, function try_parse_http_request()
  2. Note that after the header parsing loop (line 165), there is no check for is_chunked && has_content_length
  3. Compare with crates/openshell-sandbox/src/l7/rest.rs lines 265-269 which explicitly rejects this case
  4. Craft a request with both headers:
    POST /v1/chat/completions HTTP/1.1
    Host: api.example.com
    Content-Length: 100
    Transfer-Encoding: chunked
    
    5
    hello
    0
    
    
  5. The inference parser accepts and processes via chunked; a downstream server may read 100 bytes via CL

Environment

  • Code review — no runtime environment needed
  • Applies to current main branch (commit 0ac1fbd2)
  • File: crates/openshell-sandbox/src/l7/inference.rs

Logs

N/A — static code analysis finding.

Agent-First Checklist

  • I pointed my agent at the repo and had it investigate this issue
  • I loaded relevant skills (e.g., debug-openshell-cluster, debug-inference, openshell-cli)
  • My agent could not resolve this — the diagnostic above explains why

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions