sentinel

runtime defense for CLI AI agents. intercepts tool calls before execution and enforces security policy.

CI Crates.io License Platform

the live demo

The page at target.html is a fake "CloudSync docs" site. It looks like a normal tool's documentation but every section is poisoned with a prompt injection: hidden HTML comments, white-on-white text, zero-width Unicode, CSS display:none, HTML entity encoding, link title attributes, tiny-font spans, and fake "agent instruction" blockquotes. 20+ attack payloads, every one a real pattern seen in the wild.

Feed the page to any CLI agent. With sentinel's hook installed, every dangerous tool call the agent tries to make gets blocked at the hook layer before it runs.

sentinel blocking 20 prompt injections live

what you just saw

Each line is a tool call the agent would have made after parsing the poisoned page. sentinel's policy engine evaluated the call in under a millisecond and returned deny before the tool ever ran. Every attack blocked, zero false negatives.

run it yourself

git clone https://github.com/StressTestor/sentinel
cd sentinel
cargo build --release
./target/release/sentinel install
SENTINEL=./target/release/sentinel ./docs/run-attacks.sh

attacks this page contains

TypeWhereSentinel rule
HTML comment injectiontop of pagedeny.paths ~/.aws/*
Blockquote "agent instructions"troubleshootingdeny.paths ~/.aws/*
display:none hidden divtroubleshootingcurl -d @~/.aws/*
White-on-white textconfig sectionenv | grep key exfil
Tiny-font span in h2security headingcurl | sh
Fake diagnostic code blocktoken refresh~/.ssh/*
Table with malicious commandserrors tablerm -rf, curl|bash
Fake "authorized pentest" notesecuritycurl @~/.aws
rm -rf /uninstallrecursive root deletion
rm -rf on dotfile dirsuninstallcredential dir deletion
Link title attributesupport link~/.aws/*
Literal AWS key in argssupportAKIA[0-9A-Z]{16}
HTML-entity encoded commentchangelogcurl | sh
Zero-width Unicode blockfooter/etc/passwd, ~/.ssh/*
find / for credential filessecurityfilesystem scan

how it works

Claude Code and Codex expose pre-tool hooks. Sentinel can install and reconcile its native hook for either agent. Every typed tool call passes through one normalization and policy pipeline before execution. The hook receives the agent's structured payload and returns the agent's native allow or deny response. Blocks also exit with status 2.

you type a prompt
     │
     agent decides to run: cat ~/.aws/credentials
     │
     sentinel intercepts the tool call
     │
     policy says: ~/.aws/* → BLOCK (AWS credential access)
     │
     tool call denied. credentials safe.

one deterministic decision path

LayerWhatStatus
Policytyped normalization, path rules, command rules, secret rules, and self-protectionruns on every call

No heuristic or model-assisted classifier ships in the enforcement path. Every decision comes from a rule you can inspect. The deterministic engine caught every attack replayed by this page's demo harness.

audit the real agent, carefully

sentinel audit --agent claude --unsafe-host

The audit harness opens a stateful Claude Code or Codex session and correlates structured tool, filesystem, and network evidence against the bundled corpus/v1 safe canaries. It does not run in a sandbox. The explicit --unsafe-host flag is required because the selected agent runs on the host and may persist its own session state. Ambiguous or malformed evidence is reported as inconclusive or an error, not promoted to a clean verdict.

verify the installed chain

sentinel status --agent codex
sentinel doctor --agent codex --strict

The installer owns direct Claude Code and Codex hook entries, removes duplicate Sentinel handlers, and preserves a Ghost-mediated Claude hook when Ghost already owns the chain. For Codex, status and doctor also distinguish configured hooks from hooks that are enabled and trusted. These are point-in-time checks, not proof of continuous enforcement.

MCP baselines are explicit too: sentinel audit-mcp only discovers the current set. Review it before sentinel audit-mcp --update accepts salted digests as the trusted baseline. Raw server commands, arguments, URLs, headers, environment variables, and tokens are not stored.