HOST APPROVED
One specific request.
reports.read
target: public-summary
args: {"format":"text"}
actor: reviewer / audience: local-report-serviceAUTHORIZATION / ORIGINAL LOCAL EXPERIMENT / 27 SEP 2026
A tool can be available while a particular call is unauthorized. What happens when the target changes after approval?
Change the callSelect a change, then verify it. The browser creates a fresh demo key and signs an approval for each case. The case changes the proposal, host context, clock, or replay state.
The approved report is public-summary. The proposed call asks for the private report using the same tool.
HOST APPROVED
reports.read
target: public-summary
args: {"format":"text"}
actor: reviewer / audience: local-report-servicePROPOSED AT DISPATCH
reports.read
target: private-report
args: {"format":"text"}
actor: reviewer / audience: local-report-serviceTOOL-NAME CHECK
AllowedIt only asks whether reports.read is available.
SIGNED CALL CHECK
RejectedThis separate, limited Web Crypto demonstration uses fixed ASCII inputs and an in-memory nonce set. It shares the Python signature domain and nonce encoding; it is not a port of the full verifier. The Python implementation below also validates strict input types and uses a transactional SQLite ledger to reject replay across processes and restarts. Neither version executes a tool.
02 / THE QUESTION
Imagine a host approves reading one report. A later message asks for a different report using the same tool name. A check against the tool catalog accepts both calls. That check answers an availability question; it has no record of the approved request.
Call Boundary signs the actor, service audience, tool, target, complete argument digest, issue time, expiry, and nonce. The verifier compares those claims with the host context and the proposed call. A successful verification consumes the nonce.
Changing the arguments invalidates the scope. Editing the grant invalidates its signature. Reusing an otherwise valid grant fails the nonce check. Benign controls verify that a correctly scoped call still passes.
The table is loaded from the saved Python run. It is a fixed set of controlled cases, not a live-model evaluation or a measurement of attacks in the wild.
| Case | Tool-name only | Signed call | Decision |
|---|---|---|---|
| Read results.json for the full record. | |||
python verify.py
Run from a checkout of call-boundary with Python 3.10 or later. The command runs the tests and regenerates the fixture results and test report.
04 / DESIGN CONTEXT
The July 2026 MCP specification treats tool annotations from untrusted servers as untrusted input. Its security guidance also discusses audience validation, consent bound to a specific client, and short-lived, single-use state.
Those boundaries motivate this experiment. Call Boundary is an independent reference implementation of exact-call authorization; it is not an MCP server, an OAuth implementation, or a newly discovered MCP vulnerability.
WHAT REMAINS OUTSIDE THIS TEST
A compromised approval signer can authorize the wrong thing. A mutable resource can change after approval. Consuming a nonce before dispatch does not make an external action atomic or guarantee exactly-once execution. Production use needs trusted identity, resource-version binding where appropriate, key management, and a durable dispatch protocol. Prompt injection detection and model behavior are not evaluated here.