Your AI coding agent just read your .env file.
Not on purpose. You asked it to fix a bug in your config loader, so it read the config file to understand the format. That config had AWS_SECRET_ACCESS_KEY in it. Now that key is sitting in the context window.
And from here, the agent can include that key in anything. A curl command. A file write. A code snippet it generates as an "example." Not because it's attacking you. Because the key is in context and the model thinks it's relevant.
No sandbox catches this. The file was inside your project folder. The agent had permission to read it. Everything worked exactly as designed.
this is the gap
Every AI agent security tool I've looked at focuses on blocking dangerous actions. Don't run rm -rf /. Don't execute SQL drops. Don't call sketchy URLs.
That matters. But the dangerous moment isn't always when the agent does something. Sometimes it's when the agent reads something and sensitive data quietly enters the context window.
Think about it:
- Agent reads
config.yaml(totally allowed, it's in your project folder) - That file has
STRIPE_SECRET_KEY=sk_live_...in it - Key is now in the context window
- Three turns later, the agent writes a test file with the key as a "realistic example"
- That test file gets committed and pushed
Nothing here looks like an attack. No exfiltration. No curl to an external URL. Just a read, then a write, with a secret accidentally carried between them.
so I built something
I kept hitting this while running AI agents on my own stuff. Started logging everything, every file read, every command, every network request, and realized the scariest things weren't the obvious attacks. They were the quiet reads.
Rampart is an open-source policy engine that sits between AI agents and your OS. It checks every tool call before execution. But the important part is it also scans tool responses before they reach the agent.
- name: block-credential-leak
match:
tool: [read, exec]
rules:
- action: deny
when:
response_matches:
- "AKIA[0-9A-Z]{16}" # AWS access keys
- "-----BEGIN.*PRIVATE KEY-----" # SSH/TLS keys
- "ghp_[a-zA-Z0-9]{36}" # GitHub tokens
- "sk-[a-zA-Z0-9]{20,}" # Stripe/OpenAI keys
Agent reads a file containing a secret, Rampart blocks the response before the agent sees it. The secret never enters context. Attack chain breaks at step 2 instead of step 5.
other stuff it does
Response scanning is the thing I think is most underappreciated but Rampart also handles the basics.
Need to temporarily allow something that got blocked? Allow it for an hour:
rampart allow "docker build *" --for 1h
Expires automatically. --once for single use.
Don't want to write policy from scratch? Run in monitor mode, then generate rules from what your agent actually did:
rampart init --from-audit ~/.rampart/audit/
Works with basically everything. Openclaw, Claude Code, Codex, Cline, Cursor, any MCP server, any CLI tool:
rampart setup claude-code # native hooks
rampart setup codex # LD_PRELOAD wrapper
rampart wrap -- aider # shell wrapping
rampart mcp -- npx server # MCP proxy
under the hood
Rampart uses different interception depending on the agent.
For Claude Code and Cline, it registers native hooks at the PreToolUse lifecycle point. For Codex and agents that spawn subprocesses, it injects via LD_PRELOAD so every child process goes through the policy engine. For anything else, it wraps $SHELL.
All three feed into the same YAML policy engine. Evaluation is almost instant, and everything gets logged to a hash-chained audit trail.
a fun bug I found
While integrating with OpenClaw, I found that it wraps every command in /bin/bash -c <command>. Our policy had:
command_matches:
- "cat **/.ssh/id_*"
But the actual string was /bin/bash -c cat ~/.ssh/id_rsa 2>&1. Glob didn't match. Credential reads were getting through.
We added shell wrapper stripping to the normalizer. It now extracts the inner command before matching. But it was a good reminder that the gap between what you think you're blocking and what's actually hitting your engine can be bigger than you expect.
try it
brew tap peg/rampart && brew install rampart
rampart setup claude-code
Single Go binary. Apache 2.0. Ships with 45 rules out of the box.
GitHub: github.com/peg/rampart
Docs: docs.rampart.sh
If you're running AI agents on a codebase with secrets in it (so, all of us), the context window is the attack surface nobody's watching.
Top comments (0)