agentfence

mcp
Guvenlik Denetimi
Uyari
Health Uyari
  • License — License: Apache-2.0
  • Description — Repository has a description
  • Active repo — Last push 0 days ago
  • Low visibility — Only 5 GitHub stars
Code Gecti
  • Code scan — Scanned 12 files during light audit, no dangerous patterns found
Permissions Gecti
  • Permissions — No dangerous permissions requested

Bu listing icin henuz AI raporu yok.

SUMMARY

Policy firewall for AI agents and MCP tools. Intercepts tool calls, enforces allow/deny/ask rules, redacts secrets, validates arguments, and writes auditable logs before agents touch your filesystem, GitHub, browser, or APIs.

README.md

AgentFence

CI
Latest release
Go version
License: Apache-2.0

Stop unsafe agent tool calls before they reach your MCP server

AgentFence is a local tool-call firewall. It evaluates the exact MCP tool and
arguments, decides allow / deny / ask before forwarding, and writes a
redacted audit receipt you can verify offline.

flowchart LR
    A["Agent tool call"] --> B{"AgentFence policy"}
    B -->|ALLOW| C["MCP server"]
    B -->|DENY / ASK| D["Stop before side effect"]
    B --> E["Redacted receipt"]

See the boundary in under a minute

The maintained, offline demo runs AgentFence in front of a real MCP stdio
session. An allowed read returns prompt-injected text; the resulting .env
write is denied before the upstream server sees it.

git clone https://github.com/dgenio/agentfence.git
cd agentfence
./examples/demo-blocked-call.sh
AgentFence flagship MCP demo
ALLOW filesystem.read path=project-notes.txt -> upstream
DENY filesystem.write path=.env -> BlockedByPolicy before upstream
PROOF upstream received tools: ["filesystem.read"]
PASS safe read executed; injected .env write blocked before side effect.

The demo's tiny policy,
exact MCP requests, and
expected audit receipt
are committed and exercised in CI. The full command also prints the normalized
receipt and verifies its hash chain. The scenario explanation
shows how the proof works.

Security boundary: AgentFence governs tool calls that pass through its
configured CLI/proxy boundary. It is not a sandbox and does not prevent prompt
injection; it limits what a successful injection can cause at mediated tool
boundaries. Calls that bypass AgentFence are outside its control, and ask
requires a trustworthy approval path. See CLAIMS and
when not to use AgentFence.

AgentFence is a single, local Go binary with no account or built-in telemetry.
It can wrap an MCP stdio server, gate a streamable-HTTP server, or evaluate
recorded tool calls in CI. Policies are deny-by-default; audit logs can be
hash-chained and signed.

Who it's for: security and platform operators who need to gate agents they
did not write, with a policy and audit trail they control.

New here? Follow the 10-minute Quickstart — from
install to a policy-gated MCP setup with an observed allow and deny. Then see
the Daily Driver guide for day-to-day operation and
CLAIMS for what AgentFence does and does not promise.

VeriCordon: inspectable authorization evidence in CI

Project site: vericordon.diogofcul.chatgpt.site

Generate inspectable authorization evidence for the exact calls and policy
AgentFence evaluated.
VeriCordon turns a policy, representative call JSONL,
and optional policy fixtures into a human-readable report.md plus a versioned
report.json.

- uses: dgenio/agentfence/[email protected]
  with:
    policy: agentfence.yaml
    calls: testdata/tool-calls.jsonl
    tests: testdata/policy-tests.yaml

The safe downloadable artifact excludes raw audit.jsonl by default. Missing
evidence stays partial / not_evaluated; exact-action + effective-policy
binding is reported only for the calls whose supplied audit evidence supports
it. No account or hosted service is required.

See the VeriCordon authorization-evidence guide for
the copy/paste workflow, minimal inputs, a real missing-evidence example, the
fresh-consumer 3/3 binding result, and the explicit non-claims.

Current status

AgentFence is in active development. The table below distinguishes what works
today from what is planned. Do not assume planned features are usable yet.

Capability Status Where to read more
JSONL batch policy evaluation (check) Implemented Quickstart
Allow / deny / ask decisions Implemented docs/policy-language.md
Path, argument, URL, and shell-command constraints Implemented docs/policy-language.md
Tool groups and wildcard matching Implemented docs/policy-language.md
Strict policy validation (validate) Implemented Quickstart
Single-call trace (explain) Implemented agentfence explain --help
Policy fixture tests (policy test) Implemented examples/policy-tests.yaml
Regex-based redaction of audit values Implemented docs/policy-language.md
Structured output modes (text / json / jsonl) Implemented agentfence check --help
CI gating via --fail-on Implemented agentfence check --help
VeriCordon Markdown + JSON authorization evidence Implemented docs/evidence-bundle.md
Pre-built release binaries Implemented Pre-built binaries
Detection / prevention / audit-only / dry-run modes Documented docs/modes.md
Interactive TTY approval for ask decisions Implemented Approval and dry-run
Approval timeout with default-deny Implemented Approval and dry-run
Dry-run evaluation mode Implemented Approval and dry-run
MCP stdio proxy (agentfence proxy) Implemented docs/integration-guide.md, docs/architecture.md
Policy enforcement on intercepted tools/call Implemented docs/integration-guide.md
Stateless MCP 2026-07-28 tool-call shape/headers Tested examples/hero-requests.jsonl, internal/httpproxy
Tamper-evident hash-chained audit logs Implemented docs/threat-model.md
Ed25519-signed audit events (--sign-key) Implemented docs/audit-event-schema.md, docs/threat-model.md
Audit anchors (audit anchor / verify --anchor) Implemented docs/threat-model.md
Audit-log rotation and retention (--audit-max-*) Implemented docs/threat-model.md
Durable audit writes (--audit-fsync) Implemented docs/threat-model.md
External audit sinks (--audit-sink syslog/HTTP) Implemented docs/threat-model.md
Audit event JSON Schema Implemented docs/audit-event-schema.md
Audit-log summarisation (audit summarize) Implemented agentfence audit summarize --help
weaver-spec trace export (audit export) Implemented docs/interop.md
Fuzz coverage for parser, glob, and redaction Implemented make fuzz
MCP streamable-HTTP proxy (agentfence proxy-http) Implemented docs/architecture.md, docs/integration-guide.md
Confused-deputy / taint escalation Implemented docs/threat-model.md, docs/policy-language.md
Reusable policy packs (init --pack) Implemented docs/policy-language.md
GitHub Action for CI policy checks Implemented docs/integration-guide.md
Typed reason codes on every decision Implemented docs/audit-event-schema.md
Structured operational logging (--log-format json) Implemented docs/observability.md
Decision metrics (check --metrics) Implemented docs/observability.md
Prometheus metrics endpoint (--metrics-listen) Implemented docs/observability.md

Why this exists

Tool-capable agents are useful, but they can also be risky:

  • Prompt injection can trigger unsafe calls.
  • Agents may take destructive actions too quickly.
  • Sensitive values can leak into logs.
  • Teams need an audit trail of what was allowed, denied, or sent for approval.

AgentFence is a practical local control point before execution.

Install

Install script (Linux/macOS)

curl -fsSL https://raw.githubusercontent.com/dgenio/agentfence/main/scripts/install.sh | sh

The script detects your OS/arch, downloads the matching release archive, and
verifies it against checksums.txt (failing closed on a mismatch) before
installing to ~/.local/bin. Pin a version or change the directory with
AGENTFENCE_VERSION / AGENTFENCE_INSTALL_DIR.

Homebrew (macOS/Linux)

brew install dgenio/tap/agentfence

Installs the binary plus shell completions and the man page. The tap is updated
automatically on each release.

Windows (Scoop / winget)

scoop bucket add dgenio https://github.com/dgenio/scoop-bucket
scoop install agentfence
# or
winget install dgenio.agentfence

Container image

A minimal, non-root, multi-arch (amd64/arm64) image is published to GHCR:

docker run --rm ghcr.io/dgenio/agentfence:latest version

See docs/distribution.md for
running the HTTP proxy in a container with a mounted policy and audit-log
volume.

Pre-built binaries

Pre-built binaries for Linux, macOS, and Windows (amd64 and arm64) are
published on the GitHub Releases
page for each tagged release. Each release includes a checksums.txt, a cosign
signature, and an SBOM for verification (see
docs/distribution.md).
Download the archive matching your platform, extract it, and put the
agentfence binary on your PATH. Archives also bundle shell completions
(completions/) and the man page (manpages/agentfence.1).

Build from source

go build -o agentfence ./cmd/agentfence

To embed a release version at build time (compatible with goreleaser):

go build -ldflags "-X main.Version=0.1.0" -o agentfence ./cmd/agentfence

Or via the project Makefile:

make build VERSION=0.1.0

Quickstart

Run the built-in demo:

./agentfence demo

Run policy checks against example tool calls:

./agentfence check --policy examples/policy.yaml --call examples/tool-calls.jsonl

Write audit events to an append-only, owner-readable log:

./agentfence check --policy examples/policy.yaml --call examples/tool-calls.jsonl --audit-log audit.jsonl

Sign each event (writer authentication), rotate the log, and ship a copy to an
external sink — then verify the chain and the signatures offline:

./agentfence audit keygen --private audit.key --public audit.pub
./agentfence check --policy examples/policy.yaml --call examples/tool-calls.jsonl \
  --audit-log audit.jsonl --tamper-evident --sign-key audit.key \
  --audit-max-size 10485760 --audit-keep 5 --audit-sink syslog://127.0.0.1:514
./agentfence audit verify --log audit.jsonl --pubkey audit.pub

Publish an anchor so a third party can later detect silent deletion or
truncation, then check the log against it:

./agentfence audit anchor --log audit.jsonl --out audit.anchor.json   # commit this somewhere you don't control
./agentfence audit verify --log audit.jsonl --anchor audit.anchor.json

Sign the anchor so a verifier can confirm it was not itself swapped for one
naming an earlier event:

./agentfence audit anchor --log audit.jsonl --out audit.anchor.json --sign-key audit.key
./agentfence audit verify --log audit.jsonl --anchor audit.anchor.json --anchor-pubkey audit.pub

Get machine-readable output for CI pipelines:

./agentfence check --policy examples/policy.yaml --call examples/tool-calls.jsonl --output json
./agentfence check --policy examples/policy.yaml --call examples/tool-calls.jsonl --output jsonl | jq '.decision'

check --summary <file> writes a compact JSON gate summary (per-decision
counts, top denied tools/reasons, and whether --fail-on matched) alongside the
decision stream, so CI can surface "what was denied" without recomputing it with
jq. Write it to a file for a clean machine-readable artifact — it is
produced even when --fail-on fails the run. (--summary - writes to stderr
instead, which is convenient for logs but, on a gate failure, also carries
diagnostic lines and so is not pure JSON.)

./agentfence check --policy examples/policy.yaml --call examples/tool-calls.jsonl \
  --no-interactive --fail-on deny --output json --summary gate-summary.json

policy test and audit verify share the same --output text|json convention
as check, explain, and audit summarize, so every gate the pipeline runs
can be consumed structurally while preserving each command's exit code:

./agentfence policy test --policy examples/policy.yaml --tests examples/policy-tests.yaml --output json
./agentfence audit verify --log audit.jsonl --output json

Validate a policy file before use (catches typos and unknown fields):

./agentfence validate --policy examples/policy.yaml

Approval and dry-run modes

check exposes three operator controls for the ask decision and for
"evaluate without enforcing" workflows:

  • --no-interactive — never prompt; auto-deny any ask decision. The audit
    reason is non-interactive: ask auto-denied. Use this in CI.
  • --approval-timeout <duration> — bound the wait for a y/N response (e.g.
    30s, 2m). On expiry the call is denied with reason approval timeout.
    0 (the default) waits forever.
  • --dry-run — evaluate policy and write audit records but never invoke the
    approver and never propagate a non-zero exit from --fail-on. Each audit
    record carries "mode": "dry_run" so downstream readers can distinguish
    simulated decisions from enforced ones. Text output is suffixed with
    [dry-run].

Typical CI invocation:

./agentfence check \
  --policy policy.yaml --call calls.jsonl \
  --no-interactive --approval-timeout 30s --fail-on deny,ask

Run the same input through --dry-run first to see what would happen without
failing the pipeline.

Initialize a starter policy in your current directory:

./agentfence init

Check the installed version:

./agentfence version

List commands and flags:

./agentfence --help

Run AgentFence as an MCP stdio proxy in front of any MCP server:

./agentfence proxy \
  --policy examples/policy.yaml \
  --audit-log audit.jsonl \
  -- \
  npx -y @modelcontextprotocol/server-filesystem /path/to/workspace

Or gate a remote MCP server reached over streamable HTTP / SSE:

./agentfence proxy-http \
  --policy examples/policy.yaml \
  --upstream https://mcp.example.com/mcp \
  --listen 127.0.0.1:8787 \
  --audit-log audit.jsonl

Point your MCP client at http://127.0.0.1:8787; AgentFence evaluates each
tools/call with the same decision, redaction, approval, and audit semantics
as the stdio proxy, and relays everything else (including SSE streams)
transparently. See docs/integration-guide.md
for Claude Code and VS Code configuration, audit-log inspection, and
troubleshooting.

Scaffold a policy from curated policy packs instead of starting from a
blank file:

./agentfence init --pack filesystem,github,shell

This writes one pack file per surface plus an agentfence.yaml that imports
them; redeclare any tool key in agentfence.yaml to override a pack rule.

Summarise an existing audit log to see which tools are most active and which
rules dominate the deny pile:

./agentfence audit summarize --log audit.jsonl
./agentfence audit summarize --log audit.jsonl --output json --top 20

The text output reports totals, decision counts, schema versions, top tools
(overall, denied, allowed), and top reasons. The JSON output has the same
fields under stable snake_case keys for automation. Malformed JSONL lines are
counted as malformed and never abort the run.

Demo output

Running the built-in demo against the bundled example tool calls produces the
output below. The first line of each pair is the human-readable decision; the
second line is the JSONL audit event with secret-looking values redacted.

$ ./agentfence demo
AgentFence demo:
call_001 filesystem.read -> allow (tool filesystem.read matched explicit policy rule)
{"schema_version":"4","session_id":"<session_id>","seq":1,"timestamp":"<rfc3339>","call_id":"call_001","tool":"filesystem.read","decision":"allow","reason":"tool filesystem.read matched explicit policy rule","reason_code":"rule_match","arguments":{"path":"README.md"}}
call_002 filesystem.write -> deny (path ".env" denied by pattern ".env")
{"schema_version":"4","session_id":"<session_id>","seq":2,"timestamp":"<rfc3339>","call_id":"call_002","tool":"filesystem.write","decision":"deny","reason":"path \".env\" denied by pattern \".env\"","reason_code":"path_denied","arguments":{"content":"OPENAI_[REDACTED:generic_secret_assignment]","path":".env"}}
call_003 github.create_issue -> ask (tool github.create_issue matched explicit policy rule)
{"schema_version":"4","session_id":"<session_id>","seq":3,"timestamp":"<rfc3339>","call_id":"call_003","tool":"github.create_issue","decision":"ask","reason":"tool github.create_issue matched explicit policy rule","reason_code":"rule_match","arguments":{"body":"Created by an agent","repo":"dgenio/agentfence","title":"Demo issue"}}
call_004 github.delete_repo -> deny (tool github.delete_repo matched explicit policy rule)
{"schema_version":"4","session_id":"<session_id>","seq":4,"timestamp":"<rfc3339>","call_id":"call_004","tool":"github.delete_repo","decision":"deny","reason":"tool github.delete_repo matched explicit policy rule","reason_code":"rule_match","arguments":{"repo":"dgenio/agentfence"}}

./agentfence check against the example policy and tool calls produces the
same decisions plus a one-line summary:

$ ./agentfence check --policy examples/policy.yaml --call examples/tool-calls.jsonl
call_001 filesystem.read -> allow (tool filesystem.read matched explicit policy rule)
{"schema_version":"4","session_id":"<session_id>","seq":1,"timestamp":"<rfc3339>","call_id":"call_001","tool":"filesystem.read","decision":"allow","reason":"tool filesystem.read matched explicit policy rule","reason_code":"rule_match","arguments":{"path":"README.md"}}
call_002 filesystem.write -> deny (path ".env" denied by pattern ".env")
{"schema_version":"4","session_id":"<session_id>","seq":2,"timestamp":"<rfc3339>","call_id":"call_002","tool":"filesystem.write","decision":"deny","reason":"path \".env\" denied by pattern \".env\"","reason_code":"path_denied","arguments":{"content":"OPENAI_[REDACTED:generic_secret_assignment]","path":".env"}}
call_003 github.create_issue -> ask (tool github.create_issue matched explicit policy rule)
{"schema_version":"4","session_id":"<session_id>","seq":3,"timestamp":"<rfc3339>","call_id":"call_003","tool":"github.create_issue","decision":"ask","reason":"tool github.create_issue matched explicit policy rule","reason_code":"rule_match","arguments":{"body":"Created by an agent","repo":"dgenio/agentfence","title":"Demo issue"}}
call_004 github.delete_repo -> deny (tool github.delete_repo matched explicit policy rule)
{"schema_version":"4","session_id":"<session_id>","seq":4,"timestamp":"<rfc3339>","call_id":"call_004","tool":"github.delete_repo","decision":"deny","reason":"tool github.delete_repo matched explicit policy rule","reason_code":"rule_match","arguments":{"repo":"dgenio/agentfence"}}

4 call(s) processed, 0 parse error(s): allow=1 deny=2 ask=1

Timestamps are real time.RFC3339Nano values at runtime, and session IDs are
UUIDs generated per run. They are shown as placeholders here so this section
does not need to be updated on every build.

Example policy

version: "0.1"
defaults:
  decision: deny
tools:
  filesystem.read:
    decision: allow
  filesystem.write:
    decision: ask
  github.create_issue:
    decision: ask
  github.delete_repo:
    decision: deny

See examples/policy.yaml for the full policy including constraints and redaction patterns.

Threat model summary

AgentFence is built to reduce practical risks from agent tool calls:

  • prompt injection
  • confused deputy behavior
  • accidental destructive actions
  • secret leakage through logs
  • excessive default permissions

See docs/threat-model.md for the full threat model
(including the MCP proxy threat surface, confused-deputy-via-MCP-proxy, and
audit-log integrity), docs/architecture.md for the
evaluation flow, and docs/modes.md for the
detection/prevention/audit-only/dry-run mode taxonomy.

See the confused-deputy guard in action with the runnable, hermetic
examples/taint-scenario/: an allowed read returns
untrusted text, and a later write reusing that text is blocked because its
argument was derived from untrusted output.

AgentFence is not a sandbox. It enforces policy before a tool call executes;
it does not contain a tool call that has already been forwarded. Pair it with
OS-level isolation for defense in depth.

Part of the Weaver Stack

AgentFence is the external policy edge of the Weaver Stack — a set of
small, composable tools for building and operating safer AI agents. Each works
standalone; together they cover an agent's lifecycle:

   author & test          build & run            operate the edge          learn
  ┌──────────────┐     ┌──────────────────┐    ┌────────────────────┐   ┌──────────────┐
  │  vibeguard   │     │   agent-kernel   │    │     AgentFence     │   │ lessonweaver │
  │  (dev-time)  │     │ (in-process      │    │  (external policy  │   │  (learning   │
  │              │     │  firewall)       │    │   edge)            │   │   loop)      │
  └──────────────┘     └──────────────────┘    └────────────────────┘   └──────────────┘

        agent ──tool calls──▶  AgentFence  ──allow / deny / ask──▶  MCP servers / tools
                               (+ tamper-evident audit) ──deny/ask traces──▶ lessonweaver
  • AgentFence (this repo) — the external gate: an operator-controlled policy
    boundary in front of any MCP server or tool-call pipeline.
  • agent-kernel — the in-process firewall compiled into an agent application.
  • vibeguard — dev-time guardrails for agent code.
  • lessonweaver — turns recurring deny/ask traces into reviewed policy lessons.

All of these are optional. AgentFence works standalone with any agent and has
no hard dependency on any sibling.

Relationship to agent-kernel

AgentFence is the external gate in a layered approach to agent safety:

  • AgentFence (this project): a standalone CLI and MCP stdio proxy
    that sits outside the agent process. It is configured by an operator and
    decides allow / deny / ask for each tool call before it reaches the tool
    server. Use AgentFence when you want a policy layer that does not require
    modifying the agent or the application embedding it.
  • agent-kernel: an embeddable runtime/library layer for applications that
    build their own agent on top. It runs inside the agent process and is
    configured by the application author.

The two are complementary. An application can embed agent-kernel for
in-process safety and also run behind agentfence for an operator-controlled
policy boundary. If you only need one, pick AgentFence when the policy author
is not the application author, and pick agent-kernel when you are building
an agent application and want safety guarantees compiled in.

For a worked, side-by-side comparison of the same policy intent at each
integration point, see
docs/edge-proxy-vs-kernel.md. For a supervisor
gating many workers through AgentFence, see
docs/puppetmaster-integration.md.

Roadmap

The initial phased roadmap (harden the MVP → policy language → MCP proxy →
trustworthy audit logs) is complete, along with signed audit logs and a signed
multi-channel release. Current direction — response-side policy, more policy
packs, and broader client-config recipes — lives in
ROADMAP.md, which tracks the
roadmap-labeled issues
so this list can't drift.

Non-goals

  • Detecting or preventing prompt injection inside the model.
  • Sandboxing an MCP server or containing code after a call is forwarded.
  • Governing tool paths that bypass the configured AgentFence proxy or gate.
  • Proving that an operator-authored policy is correct or sufficiently strict.
  • Replacing host, container, or network isolation.

Contributing

See CONTRIBUTING.md for local-development setup, test
conventions, and PR guidelines. The short version:

make ci

before opening a pull request. CI runs the same command.

Most contributions here come from AI coding agents. If that's you, read
AGENTS.md first (a thin pointer to the make ci gate,
high-churn files, and the conventions in CONTRIBUTING.md).

By participating you agree to abide by our
CODE_OF_CONDUCT.md. Release history is tracked in
CHANGELOG.md.

Security

To report a vulnerability, please follow the coordinated-disclosure process in
SECURITY.md — do not open a public issue for security reports.

License

Apache-2.0. See LICENSE.

Yorumlar (0)

Sonuc bulunamadi