diff --git a/README.md b/README.md index 14ddb5d..163d963 100644 --- a/README.md +++ b/README.md @@ -36,6 +36,11 @@ allowlist, argument filtering, and response redaction. A trading server can be allowed to read quotes and denied the ability to place an order, and the denial is enforced at the wire, not by asking the model nicely. +The allowlist filters `tools/list` as well, so a denied tool is never advertised +to the model in the first place. It cannot attempt what it cannot see. The list is +default-deny, so a tool the policy has never heard of stays blocked until someone +adds it rather than allowed until someone notices. + The browser UI is the other half of the idea. It can add and edit every secret in the store, and it **never displays one**. No endpoint behind it returns plaintext — the detail view shows `sk-l...c9ae` and nothing more — so a stolen session diff --git a/docs/mcp-guardrails.md b/docs/mcp-guardrails.md index 73575e9..7bc0133 100644 --- a/docs/mcp-guardrails.md +++ b/docs/mcp-guardrails.md @@ -36,6 +36,11 @@ There is no soft "warn-and-allow" tier for trades — omission is a hard block. (`warnArgPatterns` still exists for credential-shaped arguments, inherited from the engine defaults.) +Denial happens twice, and the first one matters more. `tools/list` is filtered to +the allowlist before the client ever sees it, so a denied tool is never advertised +to the model — it cannot attempt what it is not shown. The call-time block is the +backstop for a client that asks for a tool it was not offered. + ## The policies Authored as standalone, reviewable files loaded by the existing policy engine: