Skip to main content

agent-police-gate

Screens what your coding agent is about to run — before it runs it — and keeps a tamper-evident record of every call.

CI License

中文 · Project page · Audit your relay · agent-police

pip install agent-police-gate
apgate install claude-code     # or: apgate install codex

Works in Claude Code and Codex CLI from one implementation — both pass the same PreToolUse payload and accept the same response, so the only per-agent artifact is a few lines of config.

Why

If your agent reaches a model through a third-party relay, that relay terminates your TLS and opens its own connection upstream. It can rewrite every JSON payload in flight, including the arguments of the tool calls your agent is about to execute. No vendor offers end-to-end integrity for tool calls today, so the client cannot verify that the command it is about to run is the command the model produced.

agent-police answers "is this endpoint tampering?" by probing it. This project answers the other half: "should this specific command run?" — inline, on every call, whether or not you ever probed the endpoint.

The attack classes come from Liu et al., Your Agent Is Mine: Measuring Malicious Intermediary Attacks on the LLM Supply Chain (arXiv:2604.08407), which measured 428 commercial relays and found 9 injecting malicious code, 17 touching the researchers' AWS canary credentials, and 1 draining an ETH private key. The paper describes three client-side defenses but does not release them.

What it does

Policy gate Screens each tool call against a rule bundle. Blocks credential exfiltration outright; forces a prompt on high-risk shapes even in YOLO / accept-edits mode.
Transparency ledger Hash-chained, append-only, local. Removing or editing a line breaks verification.
Retroactive rescan apgate rescan re-screens recorded history with today's rules — so an indicator published this week can be run against sessions from last month.

The part that matters most in practice

When you run an agent with approvals off, nothing prompts. The gate puts one prompt back, only for the shapes that actually matter — a script piped into a shell from an unrecognised host, an install redirected to a foreign registry, a URL whose real host is hidden behind a @.

Agent support, as measured

Both agents were tested live, not read about. Two behaviours are worth knowing before you install:

Codex ignores a project-level .codex/hooks.json. Only ~/.codex/hooks.json is discovered, which is where apgate install codex writes. Codex also pins trust to the hook's hash, so run /hooks once to review and trust it — until you do, it is skipped silently.

ask does nothing when approvals are off. With permission_mode: bypassPermissions, Codex ran a command the gate had answered ask on — correctly, since there was nobody to prompt. That makes every ask rule a no-op in exactly the unattended sessions that need it most, so the gate escalates ask to deny when no human is in the loop. An unanswerable prompt fails closed. Set APGATE_FAIL_OPEN=1 if you want the other behaviour.

Honest limits

This cannot tell you the model's original output. A PreToolUse hook sees the tool call after it passed through the relay; it never saw what the model actually produced. So every check here is a heuristic about whether a command looks wrong, never a comparison against ground truth.

The paper measured its own policy gate at 100% bypass by an adaptive attacker. That number applies here too. What a gate like this catches is the generic, non-adaptive rewriting that the 428-relay survey actually found in the wild — which is worth catching, and is not the same as being safe.

Closing the gap properly needs a signed response envelope from the vendor, binding model id, tool name, tool arguments, finish_reason, and a client nonce. No major tool-use API or MCP spec provides one.

How rules stay accurate

Rules are data, not code — a rule picks from a fixed predicate table and supplies literals. There is no regex from a bundle, no IO, no subprocess, and evaluation is linear in the input. A rule that can execute is a rule that can be weaponised, and this one is fetched over the network.

Accuracy is enforced mechanically, not by review:

  • every rule ships its own positive and negative cases;
  • CI runs the whole bundle against a shared corpus of ordinary developer commands;
  • a rule that blocks and fires even once on that corpus does not ship.

And provenance decides power:

Tier Reviewed May block
core yes deny / ask
community corpus only neverobserve only

That split is what lets an open rule library exist. A wrong community rule costs a line in a log, not a developer whose agent stopped working for a reason they cannot see. The schema enforces it: validate_rule rejects a community rule carrying deny.

Updates

Rules update automatically. Code does not.

This runs inside an agent with shell access. An auto-updating code channel would be a remote-execution path onto every user's machine — the exact supply-chain shape this project exists to catch. Codex agrees, structurally: it pins hook trust to the hook's hash and will not run a changed hook until you review it.

So: code moves through pip install -U, user-initiated and auditable. Rule bundles are signed with Sigstore keyless signing via GitHub Actions OIDC — this project holds no signing key — and carry a Merkle root published with each release, so a client can check that the bundle it was served is the bundle everyone else was served. Including when the mirror is ours.

Usage

apgate install claude-code        # merges into ~/.claude/settings.json (backs it up first)
apgate install codex              # merges into ~/.codex/hooks.json; then run /hooks in Codex to trust it

apgate screen "curl -sSL https://get.example.com/i.sh | bash"   # offline, one command
apgate rules                      # what is loaded, and what can block
apgate report                     # ledger summary + chain status
apgate verify                     # verify the chain alone
apgate rescan                     # re-screen history with today's rules
apgate uninstall claude-code

Exit codes for screen: 0 nothing blocking, 2 a deny rule matched.

Privacy

The ledger is local, mode 0600, and never uploaded. Secret-looking tokens are scrubbed before writing. Set APGATE_LEDGER_ARGS=0 to record only hashes of command text, or APGATE_LEDGER_OFF=1 to disable recording entirely. There is no telemetry in this release; when it arrives it will be opt-in and will never carry command text, prompts, or file contents.

Relationship to the paper

Section 6 of arXiv:2604.08407 says the authors implemented "companion client-side modules" for the three deployable defenses. Appendix A.4 then states plainly: "No public release of Mine" — and scopes that to "the compatibility and defense results in Sections 6–7", which is the same artifact holding those modules. The phrase "the released scripts" appears twice, but no link, DOI, or artifact-availability statement appears anywhere in the paper.

So the defenses are described and measured, and nothing is obtainable. This is an independent implementation, not a repackage.

Scope

Screen your own machine. This tool reads commands and never executes them.

License

Apache-2.0

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

agent_police_gate-0.1.0.tar.gz (36.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

agent_police_gate-0.1.0-py3-none-any.whl (38.2 kB view details)

Uploaded Python 3

File details

Details for the file agent_police_gate-0.1.0.tar.gz.

File metadata

  • Download URL: agent_police_gate-0.1.0.tar.gz
  • Upload date:
  • Size: 36.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for agent_police_gate-0.1.0.tar.gz
Algorithm Hash digest
SHA256 1ba7521efeb2b37737537b980d5c006ef4888f6351e99fa46220bcdb716408b5
MD5 f929738e0a3dcf876f8523744d2924a3
BLAKE2b-256 6238fccaae91ec3c9c61d12373e45e3cdc420b66763ef7befa2ff285421cd889

See more details on using hashes here.

Provenance

The following attestation bundles were made for agent_police_gate-0.1.0.tar.gz:

Publisher: release.yml on RomaCredit/agent-police-gate

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file agent_police_gate-0.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for agent_police_gate-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 4d9b78d575f1ed1d550465c748abdf35bf7de6736e01b994e1a318df36e8deb5
MD5 3fc730aafed7b259b6dc8549f9994726
BLAKE2b-256 b580c17896c8f32b8de0fc9e7b6ea94bc21c74dd4ca3d064fd5ffe0b299df3b8

See more details on using hashes here.

Provenance

The following attestation bundles were made for agent_police_gate-0.1.0-py3-none-any.whl:

Publisher: release.yml on RomaCredit/agent-police-gate

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page