What the guard checks
The guard runs in the agent’s own hooks, on your computer, with no AI model. It sees each tool step as the agent is about to run it, and each result as it comes back. This page is the complete list. For a gentler start, see Why you need the guard.
How it decides
Section titled “How it decides”- Three answers. Blocked: the step does not run, and the agent is told why and the safer way. Asked: you answer yes or no. Goes ahead: logged only.
- Asked once, then remembered for the chat, unless the table says every time. A push is remembered per destination; an MCP tool per server; a script on disk per version of the file.
- Untrusted content raises the bar. After the agent reads a web page, an MCP or network result, or a file from outside the project, pushes, sending data out, secrets and rule changes ask again even if you allowed them. After a result with signs of a prompt injection, any risky step is blocked instead, and a SessionCost line says so at once, to you and the agent. Your next message resets this; with strict mode it lasts for the whole chat.
- Commands are read the way the shell reads them: quotes joined (
.e''nvis.env), inner shells opened (bash -c,sh -c,pwsh -Command,cmd /c), heredocs, PowerShell here-strings andpython -cscripts looked into. Text that is only quoted (a commit message, an issue comment) is not taken for a command.
Blocked: the never list
Section titled “Blocked: the never list”| Check | Examples | OWASP |
|---|---|---|
| Reading or sending a secret | .env, ~/.ssh, id_rsa, .pem / .key, credentials, .npmrc / .pypirc; other stored logins: .git-credentials, GitHub CLI, Docker, Kubernetes, Azure and Google Cloud logins, Terraform state, a browser’s cookies and saved passwords; commands that print a stored login (cmdkey /list, gh auth token); Grep inside them; a key-shaped value in a command, URL or MCP call |
LLM02:2025, ASI03 |
| A secrets file in a commit | git commit that would take one into history, including what git add -A, git add . or commit -a in the same command adds; .gitignored files never count |
— |
| Printing the environment | printenv, env, Get-ChildItem env:, print(os.environ), echo $OPENAI_API_KEY |
LLM02:2025 |
| Running code from the internet | curl … | sh, iex (iwr …), bash <(curl …), download then run in one command |
ASI05 |
| Hidden commands | powershell -EncodedCommand, base64 -d … | sh |
ASI05 |
| Rewriting shared history | git push --force / -f / --force-with-lease, a + refspec, filter-branch, filter-repo |
LLM06:2025 |
| Switching off commit checks | --no-verify, commit -n, SKIP=…, HUSKY=0; marked even when refused |
LLM06:2025 |
| Persistence | crontab, schtasks /create, Register-ScheduledTask, Run keys, startup folders, systemctl enable, launchctl load, ~/.bashrc, $PROFILE |
ASI10 |
| Switching off a security tool | Defender, the firewall, SELinux, Gatekeeper | LLM06:2025 |
| Wiping | rm -rf /, rm -rf ~, Remove-Item C:\, format D:, diskpart, mkfs, dd onto a disk |
LLM06:2025, ASI02 |
| Changing the guard | its settings, log or folder, .sessioncost-allow, the agents’ hook files, disableAllHooks, installed plugins, guard off |
LLM06:2025, ASI10 |
| A poisoned MCP server’s tools | every tool of a server whose descriptions showed injection signs at the start | LLM01:2025, ASI04 |
| A risky step after an injection | any asked step below, right after a result with injection signs | LLM01:2025, ASI01 |
| Check | When | OWASP |
|---|---|---|
| Push | once per destination; a push straight to a web address every time | LLM06:2025 |
| Install | once per package for the project’s own packages | LLM03:2025, ASI04 |
| A package not in the project’s lists | every time, named (pyproject.toml, requirements*.txt, uv.lock, package.json; a folder with no list is not judged) |
LLM03:2025, ASI04 |
| Deleting files or work | once each; files the agent created in this chat go ahead. Also: throwing away changes (git checkout -- ., git restore, git stash drop), emptying a file, moving one out of the project, docker prune, kubectl delete, terraform destroy, a database client running DROP TABLE or DELETE FROM |
LLM06:2025 |
| Writing outside the project | once each; the system temp folder goes ahead | LLM06:2025 |
| A new website | once per site; well-known look-up sites (language docs, PyPI, npm, GitHub, Read the Docs…) and localhost go ahead. DNS look-ups (nslookup) and email (Send-MailMessage) ask the same way |
ASI02 |
| The agent’s own rules and checks | every time: CLAUDE.md, AGENTS.md, GEMINI.md, agent settings, .mcp.json, git hooks, pre-commit, CI workflows. A plain note in the agent’s own memory folder: once per chat |
— |
| An MCP tool that changes or sends | once per server; arguments with a path outside the project, DROP TABLE or DELETE FROM ask too |
ASI02 |
| Raising its own rights or changing the computer | every time: sudo, su, runas, chmod 777, an execution-policy bypass; new users and admin groups, services, the machine’s registry or PATH, shutting down, a container with the host’s rights, rundll32 / regsvr32 / mshta |
LLM06:2025, ASI03 |
| A script that prints a key | a script about to print a key, token or password variable | LLM02:2025, ASI03 |
| Sending data out after a key appeared | every time, once a key-shaped value came back in a tool result | LLM02:2025, ASI03 |
| A script on disk with a never-list step | sh setup.sh, python tool.py, ./build.sh: once per version of the file |
ASI05 |
| A new or changed skill, plugin or MCP server | before its first use (Claude Code) | ASI04 |
| A third try of a failing command | the same command failed twice in a row with no file changed (Claude Code) | — |
| A risky step after untrusted content | pushes, sending data out, secrets and rule changes, even if allowed before | LLM01:2025, LLM06:2025, ASI01, ASI02 |
Code written into a command (a heredoc, python -c, node -e) is only logged.
When the chat starts
Section titled “When the chat starts”Before any tool runs, the guard reads what the chat loads into the model:
- Rules and memory:
CLAUDE.md,AGENTS.md,GEMINI.md, Cursor rules, the agent’s memory for the project, and each skill’s description. Signs of a prompt injection stop risky steps for the whole chat, and the report names the file. - MCP tool descriptions: the guard asks its own short-lived copy of each local MCP server for its tool list (all at
once, at most 5 seconds) and reads every description, parameter and the server’s instructions. A poisoned server’s
tools are blocked for the chat. A project’s
.mcp.jsonserver is only started once you approved it in the agent; online servers and servers that do not answer in time are named as not checked. - Fingerprints (Claude Code): skills, plugins and MCP servers are hashed and compared with the last chat in that folder.
After each result
Section titled “After each result”- Injection signs: steering phrases, fake system tags, characters a person cannot see, and text that addresses its reader as an agent. Only a yes/no is kept, never the text. A result of the agent’s own Edit or Write is not scanned (it wrote that text); reading the file back is.
- Keys: a key-shaped value in a result is marked, and from then on anything that sends data out asks.
By agent
Section titled “By agent”Each agent’s hooks show the guard different things, so the same rules reach a little further in some agents than in others.
| Claude Code | Codex | Cursor | Antigravity | Copilot CLI / VS Code | |
|---|---|---|---|---|---|
| How it is added | the plugin | guard setup codex |
guard setup cursor |
guard setup antigravity |
guard setup copilot |
| Steps checked before they run | all tools | all tools, patches included | shell commands, MCP calls, file reads (not file edits: Cursor has no hook before an edit) | all tools | all tools |
| Asked steps | you are asked | blocked; the agent asks you in the chat, and your yes allows that step once | you are asked (a file read cannot ask, so it is blocked) | asked with force_ask, so Antigravity’s “Always allow” cannot skip it |
you are asked; in Autopilot mode, blocked |
| Results scanned for injection and keys | yes | yes | shell, MCP and file reads | no (its hook carries no result; a page still counts as untrusted) | yes |
| A line at once when a result shows injection signs | yes | sent (not tried yet) | no (in the log and report) | no | no (in the log and report) |
| Third try of a failing command | yes | no | no | no | no |
| Untrusted content lasts until | your next message | your next message | the end of the chat | the end of the chat, unless the build sends your message | your next message |
| Turn on (every chat, until off) | /livesession, or sessioncost guard on |
/livesession (added by sessioncost setup), or sessioncost guard on |
same as Codex | same as Codex | sessioncost guard on |
| Turn off | /livesession off, or sessioncost guard off |
sessioncost guard off in a terminal |
same | same | same |
| Says it is on when a chat starts | a line, and 🛡 Guard on beside the model name (terminal, desktop app) or under the message box (VS Code) | the agent says it | the agent says it | the agent says it after /livesession |
the agent says it |
When the guard itself fails, the never list still blocks and other steps go ahead, so work does not stop;
sessioncost guard fail-closed on blocks everything instead, including a step whose message the guard cannot read
(not valid JSON). Copilot lets a step run if a check takes longer than 10
seconds. Antigravity reads its hooks only when it starts: after setup, close it fully (a window reload is not
enough). On Windows a command window flashes briefly before and after each Antigravity step: that is the guard
starting, and it cannot be hidden from our side.
What it cannot do
Section titled “What it cannot do”- It matches known patterns in the text of each step. It does not understand intent, and it cannot see what a hook does not show it (see the table above). Use it with your other controls, not instead of them.
- By the time it reads a poisoned MCP description, the agent has read it too. The guard blocks that server’s tools and every risky step, but a description that only asks for a wrong answer, with no step behind it, cannot be blocked: remove that server.
- A determined program running with your rights can get around text rules. The guard catches an agent being steered; it is not a boundary against malware already on the machine.
How we test all this, and what has been tried in which agent: How we test the guard. How often it asks in real work: Why you need the guard.