Bug Description
responses_proxy strips the Responses-only conversation field from passthrough request bodies when no ResponsesState was produced, but it does not update or remove Content-Length. The forwarded body is shorter than the original client body while the original framing header can remain in effect, which is request-smuggling-sensitive at this network proxy boundary.
Evidence
apis/src/openai/responses/proxy/mod.rs:170-173 — no-ResponsesState passthrough calls strip_conversation_field(body) and returns Continue.
apis/src/openai/responses/proxy/mod.rs:200-214 — strip_conversation_field removes conversation and rewrites body.
apis/src/openai/responses/proxy/mod.rs:185-188 — only the normal rebuild path pushes a replacement content-length matching the serialized body.
apis/src/openai/responses/proxy/tests.rs:322-336 — existing passthrough test proves body mutation but does not assert Content-Length behavior.
Steps to Reproduce
- Send a
POST /v1/responses request through responses_proxy without a ResponsesState extension.
- Include a JSON body containing a top-level
conversation field and a Content-Length equal to the original body length.
- Let
on_request_body process the terminal buffered body.
- Observe that the body has
conversation stripped, but no replacement/removal for Content-Length is emitted in this path.
Expected Behavior
When the passthrough path mutates the request body, it should either set Content-Length to the new body.len() or remove the original header so framing is recalculated. It should not leave a stale client-provided content length after shortening the body.
Actual Behavior
The no-ResponsesState path mutates body via strip_conversation_field and then returns Continue without updating request headers. Only the normal ResponsesState rebuild path pushes a replacement content-length.
Recommendation
Make strip_conversation_field report whether it mutated the body and the new length, then update the forwarded Content-Length through the same header-setting/removal mechanism used by body rebuilds. Add a regression test with an original Content-Length and a stripped conversation field asserting the final header state matches the rewritten body.
Clawpatch Metadata
- Run:
20260713T070409-156e2c
- Finding:
fnd_sig-feat-apis-src-no-token-usage_84f43ba5fe
- Severity: medium
- Category: security
- Confidence: high
Bug Description
responses_proxystrips the Responses-onlyconversationfield from passthrough request bodies when noResponsesStatewas produced, but it does not update or removeContent-Length. The forwarded body is shorter than the original client body while the original framing header can remain in effect, which is request-smuggling-sensitive at this network proxy boundary.Evidence
apis/src/openai/responses/proxy/mod.rs:170-173— no-ResponsesStatepassthrough callsstrip_conversation_field(body)and returnsContinue.apis/src/openai/responses/proxy/mod.rs:200-214—strip_conversation_fieldremovesconversationand rewritesbody.apis/src/openai/responses/proxy/mod.rs:185-188— only the normal rebuild path pushes a replacementcontent-lengthmatching the serialized body.apis/src/openai/responses/proxy/tests.rs:322-336— existing passthrough test proves body mutation but does not assertContent-Lengthbehavior.Steps to Reproduce
POST /v1/responsesrequest throughresponses_proxywithout aResponsesStateextension.conversationfield and aContent-Lengthequal to the original body length.on_request_bodyprocess the terminal buffered body.conversationstripped, but no replacement/removal forContent-Lengthis emitted in this path.Expected Behavior
When the passthrough path mutates the request body, it should either set
Content-Lengthto the newbody.len()or remove the original header so framing is recalculated. It should not leave a stale client-provided content length after shortening the body.Actual Behavior
The no-
ResponsesStatepath mutatesbodyviastrip_conversation_fieldand then returnsContinuewithout updating request headers. Only the normalResponsesStaterebuild path pushes a replacementcontent-length.Recommendation
Make
strip_conversation_fieldreport whether it mutated the body and the new length, then update the forwardedContent-Lengththrough the same header-setting/removal mechanism used by body rebuilds. Add a regression test with an originalContent-Lengthand a strippedconversationfield asserting the final header state matches the rewritten body.Clawpatch Metadata
20260713T070409-156e2cfnd_sig-feat-apis-src-no-token-usage_84f43ba5fe