foreguard / a dry-run trust layer for AI agents
Rust · source-available · BUSL-1.1

Preview what your AI agent is about to do, before it does it.

Autonomous agents are powerful and unnerving for the same reason: you cannot see what they are about to do until it is already done. Foreguard sits between any MCP host and its tool server. Read-only calls pass straight through. Mutating calls are intercepted and previewed, showing the concrete effect rather than a bare verdict.

Install

One command.

cargo install foreguard

Then put it in front of the tool server your agent already uses. No agent changes, no prompt changes.

.mcp.json / claude_desktop_config.json
{
  "mcpServers": {
    "filesystem": {
      "command": "foreguard",
      "args": ["proxy", "--", "npx", "-y",
               "@modelcontextprotocol/server-filesystem", "/path"]
    }
  }
}
Prompt injection

It also tracks where the data came from.

Most defenses scan text, trying to recognise a malicious instruction by how it reads. That is an arms race against natural language. Foreguard ignores what the text says and tracks where it came from. With --taint, output from untrusted sources such as a web fetch, an inbox read, or RAG retrieval is marked. If that data later turns up inside a mutating call, it has violated Meta's Agents "Rule of Two", and the call stops for a human.

real session output · a poisoned page tries to exfiltrate
⛔  RULE-OF-TWO VIOLATION this mutation carries
    untrusted data (`attacker@evil.com`); forcing human approval.
⚠  `send_email` (high risk) · sends to attacker@evil.com
    Execute this for real? [y/N]
    ✗ denied, dry-run, nothing executed

Approve instead, and the exact call you previewed is what executes. Nothing is re-planned or re-generated between the preview and the action.

The loop

Record, review, promote.

proxy

Sit between host and tool server. Mutations are previewed with their concrete effect and never executed.

--approve

Each mutation pauses for a decision on your terminal. Only an explicit yes runs it.

--taint

Track provenance. Untrusted data reaching a mutating call forces approval automatically.

--ledger

Append a JSON line per call: what was asked, how it was judged, and what happened.

promote

Replay a recorded ledger against a live server, running the same calls you already reviewed.

plan

Score a batch of proposed tool calls offline and get a Mutation Plan, with JSON output.

Honest limits

Where the guarantee ends.

Taint tracking is best-effort, not sound, and saying so is the point. Foreguard sees tool inputs and outputs, not the model's hidden reasoning, so data the model paraphrases or re-encodes can slip a substring match. What it reliably catches is the common, un-laundered path from untrusted input to mutating action.

Where it is uncertain, it fails safe. A tainted mutation with no terminal attached is denied rather than executed. The ledger is an audit log, not a tamper-proof one.

A security tool that overstates its guarantee is worse than one that draws the boundary clearly and then holds it.

Origin

Extracted from kedge.

Foreguard does not reinvent the engine, it extracts one. The fail-safe, deny-wins tool classifier comes from kedge, a deterministic AI-agent harness. Same code, one source of truth, published as a dependency rather than forked.