Skip to content

proxy-security.md's MAX_STRING_LENGTH is spec'd but unenforced anywhere #562

Description

@Yatsuiii

Follow-up to #34 / docs/spec/proxy-security.md. #34 asked for a fuzz-tested parser with enforced resource limits before Phase 2 ships; it was closed by #44, which added the spec doc defining those limits, not by implementing them.

Verified against current main:

  • MAX_STRING_LENGTH = 1 * 1024 * 1024 # 1MB per string field (proxy-security.md line 41) is not implemented anywhere in src/ or scripts/. A single multi-hundred-KB string inside an otherwise-valid arguments payload sails through both fix: close the remaining #518 gaps in the mock upstream's JSON-RPC gate #556's and fix: close #518's gateway-side gap in _handle_mcp #561's depth/key-count caps unbounded, up to whatever the whole-body size cap happens to be.
  • MAX_PARSE_TIME_MS = 100 (line 40) is also unenforced anywhere. Not part of this issue's proposed fix - a real wall-clock bound on json.loads needs either a signal-based timeout (SIGALRM, doesn't work on the Windows CI legs this repo runs) or an executor/subprocess, which is a bigger design decision than this issue's scope.
  • MAX_REQUEST_BYTES is defined twice, disagreeing with the spec and with each other: the spec says 10MB, scripts/mock_upstream.py hard-codes 1MB, and MCPServer.__init__'s max_request_bytes default is also 1MB. Flagging here rather than picking a number myself - not obvious whether 1MB was a deliberate tightening or spec drift.

Proposing to close the MAX_STRING_LENGTH piece first, since it extends the exact validation path #556/#561 already added: the same _arg_shape_violation walk in both scripts/mock_upstream.py and src/cmcp_runtime/mcp/server.py, one more check alongside the existing depth/key-count caps.

One wrinkle, which is really the third bullet above biting the first: the spec's literal MAX_STRING_LENGTH of 1MB is exactly MAX_REQUEST_BYTES as both files currently define it. A 1MB string plus any JSON structure around it already exceeds the whole-body cap, so a check at the literal spec value can never fire before DOS-001's size rejection already has. It would be dead code. Any implementation has to pick a value meaningfully below the body cap and say why, or raise MAX_REQUEST_BYTES first. That makes this piece less unambiguous than I implied when I filed this.

MAX_PARSE_TIME_MS and the MAX_REQUEST_BYTES mismatch left open for maintainer input on the right approach before anyone builds on top of a guess.

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