jcp-gateway: everything a gated request carries to the server is sealed and flow-checked #339
Loading…
Reference in a new issue
No description provided.
Delete branch "fix/jcp-gateway-flow-checks-whole-request"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
What was open
A gated
tools/call,resources/readorprompts/getwas decided and flow-checked over its arguments, but forwarded whole. Three things reached the server without passing the flow ceiling, and a value from an untrusted read could leave by any of them:_metakey;paramsmember the method does not define;params.#336 already rebuilt task requests from the decided fields. This closes the same gap for calls.
What this changes
beside). A request that carries nothing beyond its arguments is decided over exactly the bytes it was before.protocol_meta_key):_metakeys:progressToken, and any key under a prefix MCP reserves for itself, such asio.modelcontextprotocol/. The client's runtime writes these, and a server names them back in every reply. The flow store admits every payload it labels, so folding these keys would make the first tainted request taint every request after it. They are the one part of a request the server receives unchecked.resources/readwas gated over its wholeparams,_metaincluded. Under MCP 2026-07-28 the protocol keys in every request matched the server'sio.modelcontextprotocol/serverInfoin every reply. Once one reply was admitted, every later read under a ceiling was refused as tainted. A test now reproduces this.scan_bytes), not wrapped in one JSON object. A wrapper's keys would be the same text in every request of that shape, which would carry one tainted request's label into the rest. This also replaces the wrapper #336 used for retries.Verification (build host)
cargo test -p jcp-gateway --libpasses, with 6 new tests._metaparts each on their own; the protocol-key exemption;_metastripping on reads; the unique separator; joined scanning; sealing the extras; the task_metascan; the gateway-namespace exemption; the legacy-key exemption; and the call-path extras scan.-D warningson jcp-energy and jcp-gateway).Behaviour to know
The flow store admits every payload it labels. So after a tainted request, a later request that shares 16 bytes of its own text with it inherits that taint. This includes argument or
_metastructure that repeats from request to request. It fails closed and predates this PR. This PR only stops the gateway's own joining from adding such shared text.🤖 Generated with Claude Code