Security & privacy
Network, logging, redaction, threat model.
You are being asked to install a proxy in front of your model traffic. This page is what it does, what it stores, and what it does not claim.
Network
Iris binds to 127.0.0.1 only. It does not listen on an external interface, there is no
remote component, no telemetry, and no account. If you want it reachable from another machine, you
would have to put your own tunnel in front of it — nothing in Iris does that for you.
The single outbound connection is to https://api.anthropic.com, overridable with
ANTHROPIC_PROXY_TARGET.
Request forwarding
Requests are forwarded byte-for-byte by default. Iris parses a copy of the body for analysis; the bytes that go upstream are the bytes Claude Code sent, including your credentials, which Iris neither stores nor inspects.
The one exception is opt-in wire redaction, below.
Logging — what is stored, and where
| Path | Contents | Scope |
|---|---|---|
.claude/proxy-logs/ | Request and response payloads | Per project |
.claude/history-index.json | Call index: tokens, latency, cost | Per project |
.claude/action-log.json | Tool action ledger | Per project |
~/.iris/projects/<id>/sessions/ | Envelope and decisions | Per project, outside the repo |
init adds the four in-project paths to .gitignore, so captures are not
committed by accident. Clear captured data in the UI removes only files this proxy wrote —
POST /__reset requires {"confirm":"clear"}.
Secret redaction (default on)
Before anything is written to proxy-logs/, 14 credential patterns are scrubbed:
Anthropic keys, private keys, AWS ids and secrets, GitHub / GitLab / Slack / Stripe / Google / OpenAI
keys, JWTs, bearer tokens, npm tokens, and generic api_key = … assignments. Emails too,
unless PROXY_REDACT_EMAILS=0.
Each match becomes {{kind:hash}} — stable enough to correlate the same secret across
calls, useless if the log leaks. Set PROXY_REDACT=0 to turn it off, which you should not
do.
Wire redaction (opt-in, off by default)
PROXY_REDACT_WIRE=1 changes the guarantee above. Secrets are swapped for placeholders
in the outbound request and rehydrated in the streamed response, so the model never sees the
real value but your terminal still does.
- The placeholder→value vault is memory-only and per-run. A vault on disk is just a smaller file containing all your secrets.
thinkingblocks are passed through untouched, because editing them invalidates their signature.- With this on, requests are no longer byte-identical upstream. That is the trade, and it is why it is off by default.
Guard's threat model
Guard is built for one situation: an agent with real credentials doing something consequential that nobody asked for — through a mistake, a misread instruction, or content in the context window that was written to be followed.
What it is designed to stop:
- Writes and deletes outside the project root.
- Anything touching a production environment or production credentials, when the envelope does not grant that.
- Irreversible operations proceeding without a human saying yes.
- The session quietly widening its own authority — including via an envelope the model proposes.
Structural properties it relies on, rather than judgement:
- Resolved path containment. Paths are resolved against the project root before comparison,
so
../traversal does not escape it. - The envelope lives outside the conversation. The model cannot edit the file, and a proposal granting more than the current envelope is rejected.
- Fails closed. Missing, unreadable or malformed policy resolves to ASK or stricter. There is no path that yields a silent allow.
- Deterministic and logged. No model call is involved; the same call against the same envelope always produces the same decision, and every decision is written down.
What Guard does not claim
It does not confine a process, restrict syscalls, or contain a compromised binary. It evaluates tool calls that Claude Code is about to make. A process that has already started can do whatever the operating system permits.
- Arbitrary shell is not perfectly classifiable. Recognizers cover known dangerous shapes; an unusual construction may land in ASK rather than DENY.
- The prose-stripping heuristic is a heuristic, not a shell parser.
- It is one boundary, not the boundary. Keep real credentials scoped, keep production behind separate credentials, and keep backups. Guard should not be the only thing between an agent and irreversible infrastructure.
Reporting a vulnerability
Please do not open a public issue for a security problem. Use GitHub's private advisory flow: report a vulnerability. Include the version, your platform, and a reproduction if you have one. Reports that demonstrate a Guard bypass or a redaction failure are especially valuable.