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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions