From 96ae856baa34af66d376f5443652f8aa678d6034 Mon Sep 17 00:00:00 2001 From: Yatsuiii Date: Wed, 26 Aug 2026 00:50:29 +0530 Subject: [PATCH 1/2] docs: make proxy-security.md's MAX_STRING_LENGTH derivable (#562) Follow-up from the #570 review. The document specs a per-string cap as a literal 1MB, which is the same number as the whole-body cap both implementations enforce. An implementer following the text literally produces a check that cannot fire, because a string at that size is already a request the body-size check rejects. That is worse than having no check. A missing control is visible as missing. A present one that cannot trigger passes review, passes an audit read of the source, and counts toward this Definition of Done. States the cap as a derivation of MAX_REQUEST_BYTES and writes down the invariant, so a later change to the body cap moves the string cap with it instead of silently recreating the unreachable condition at a new ratio. This matches what shipped in #570. Also records the open disagreement rather than resolving it: this document says 10MB and both implementations enforce 1MB, and nothing says whether that was deliberate tightening or drift. Left on #562 for a maintainer call, with a note telling implementers to follow the enforced cap meanwhile rather than raising a body cap to match the doc. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01KDXJ4ghkW6v56W8St2w5kg --- docs/spec/proxy-security.md | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/docs/spec/proxy-security.md b/docs/spec/proxy-security.md index 20196f88..45d0785a 100644 --- a/docs/spec/proxy-security.md +++ b/docs/spec/proxy-security.md @@ -38,9 +38,25 @@ These constants are hard-coded in the proxy implementation. They are not configu MAX_REQUEST_BYTES = 10 * 1024 * 1024 # 10MB MAX_JSON_NESTING_DEPTH = 64 MAX_PARSE_TIME_MS = 100 -MAX_STRING_LENGTH = 1 * 1024 * 1024 # 1MB per string field +MAX_STRING_LENGTH = MAX_REQUEST_BYTES // 2 # per string field, see invariant below ``` +### MAX_STRING_LENGTH is a ratio, not an absolute + +`MAX_STRING_LENGTH` must stay meaningfully below `MAX_REQUEST_BYTES`, and it is written above as a derivation rather than a literal so that it cannot drift out of that relationship. + +The invariant matters because violating it produces a check that reads like a control and can never fire. A single string at or above the whole-body cap makes a request the body-size check already rejects, so the per-string check is unreachable on every input that survives long enough to reach it. That is worse than an absent check: an absent control is visible as missing, while a present one passes review, passes an audit read of the source, and counts toward this Definition of Done. + +An implementation MUST derive the per-string cap from whatever whole-body cap it enforces. It MUST NOT restate the value as a literal, since a later change to the body cap then silently recreates the unreachable condition at a new ratio. + +### Open: MAX_REQUEST_BYTES disagrees with the implementation + +This document states 10MB. Both implementations enforce 1MB: `scripts/mock_upstream.py` and `MCPServer.__init__` in `src/cmcp_runtime/mcp/server.py`. + +At the implemented 1MB, the per-string cap this document originally stated as a literal 1MB was exactly the whole-body cap, which is how the unreachable case above was found. Deriving the cap removes the dead-code hazard at either value, but the disagreement itself is still open: nothing records whether 1MB was a deliberate tightening or drift from this spec. + +Tracked on #562. Implementers should follow the enforced body cap and the ratio above until that is settled, rather than raising a body cap to match this document. + ## Malformed Input Handling Every parse path has an explicit error handler. No input reaches undefined behavior. The error handler contract: From 5e5db8d67dd75d34824a28d80081fc98703b00bf Mon Sep 17 00:00:00 2001 From: Yatsuiii Date: Wed, 26 Aug 2026 01:01:14 +0530 Subject: [PATCH 2/2] docs: point the open body-cap question at #573 #562 was closed as completed by #570, so it is no longer a live tracker for the MAX_REQUEST_BYTES mismatch this section defers to. Filed #573 for that question specifically and points there instead. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01KDXJ4ghkW6v56W8St2w5kg --- docs/spec/proxy-security.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/spec/proxy-security.md b/docs/spec/proxy-security.md index 45d0785a..0f0b276d 100644 --- a/docs/spec/proxy-security.md +++ b/docs/spec/proxy-security.md @@ -55,7 +55,7 @@ This document states 10MB. Both implementations enforce 1MB: `scripts/mock_upstr At the implemented 1MB, the per-string cap this document originally stated as a literal 1MB was exactly the whole-body cap, which is how the unreachable case above was found. Deriving the cap removes the dead-code hazard at either value, but the disagreement itself is still open: nothing records whether 1MB was a deliberate tightening or drift from this spec. -Tracked on #562. Implementers should follow the enforced body cap and the ratio above until that is settled, rather than raising a body cap to match this document. +Tracked on #573. Implementers should follow the enforced body cap and the ratio above until that is settled, rather than raising a body cap to match this document. ## Malformed Input Handling