Redaction
Everything exec_with_secrets returns to the model, stdout and stderr, is
scrubbed first. Each occurrence of an injected secret is replaced with a
placeholder naming the secret and the encoding it was found in:
Authorization: Bearer [STRIPE_KEY:REDACTED]
QXV0aG9yaXphdGlvbjogQmVhcmVyIH[STRIPE_KEY:base64:REDACTED]Ao=
Matched by value, not by pattern
keygrant knows the actual value of every secret it injected, so it matches that
value rather than guessing at “things that look like keys”. There is no
blocklist of prefixes (sk-, ghp_, AKIA…) to fall behind when a
provider invents a new format.
Matched forms:
- plaintext;
- base64, including URL-safe base64, at every byte alignment: the same key encodes differently depending on what precedes it, so all three alignments are checked;
- hex, upper and lower case;
- URL encoding.
On the CLI
keygrant exec only redacts with --redact:
keygrant exec --redact STRIPE_KEY -- sh -c 'echo "$STRIPE_KEY"' # prints [STRIPE_KEY:REDACTED]
keygrant exec STRIPE_KEY -- ./deploy.sh # output goes to your terminal as-is
Without the flag, output streams straight to your terminal, which is what you
want when you run something yourself. If an agent calls the CLI, it must pass
--redact; the MCP tool always redacts.
Limits
Redaction is a backstop, not the boundary. The boundary is that values never enter the model’s context in the first place.
- Encodings it doesn’t know can evade it: compression, encryption, or a value split across lines.
- Files aren’t covered. If a command writes a secret into a file and the agent reads that file later with another tool, keygrant never sees it.
- Derived values aren’t covered. A token minted from your key is a different string.