Open source · Apache-2.0 · 428 relays measured, 9 injecting malicious code

Is the command your AI agent
is about to run really its own?

A cheap relay can read — and rewrite — every instruction you send.
Take 30 seconds and find out whether the one you use is clean.

How it works

Three steps. No expertise required.

Every step is copy-paste. Any term you do not recognise is explained in plain words further down.

01

Find your relay's address

It is the URL you put into Claude Code, Codex, or Cherry Studio — usually shaped like https://xxx.com/v1. Not sure where that lives? See "Plain-English glossary" below.

02

Paste it in and scan

Without a key you still learn who the endpoint really is, what relay software it runs, and whether anyone can use it without authentication. For the full probe, use a throwaway key and delete it afterwards.

03

Read the result

The report says in plain language whether it altered your commands, whether it touched your credentials, and exactly what to do next.

Before you scan

There is a five-second check. Try this first.

No tool to open, no key to hand over. Works on any relay.

Send your relay a message containing nothing but hi, then look at prompt_tokens in the response:

What you seeWhat it means
Single digits Normal. What you sent is what it forwarded.
Hundreds or thousands Somebody prepended something to your request — and those inserted tokens are on your bill.
Replace the URL and key with your own, then paste this into a terminal: curl -s https://your-relay.example.com/v1/chat/completions \ -H "Authorization: Bearer YOUR_KEY" \ -H "Content-Type: application/json" \ -d '{"model":"gpt-4o-mini","messages":[{"role":"user","content":"hi"}]}' \ | grep -o '"prompt_tokens":[0-9]*'

This only says "hi". It changes nothing on your machine or your account.

01Start with the checks that need no key

Neither of these asks for a credential. Do them first, then decide whether the full probe is worth it.

Looks only at the endpoint itself: who it is, what relay software it runs, its TLS certificate, whether it strips the upstream vendor's response headers, and whether it is an open relay anyone can use unauthenticated. Your key is never sent.

The URL you configured in your AI tool. It usually ends in /v1.
Not sure? Leave the default and try the other one if nothing comes back.

02Full probe (needs an API key for that endpoint)

AC-1 and AC-1.a can only be found by probing: we send a request whose correct answer is known verbatim — asking the model to return one specified command unchanged — then compare the returned tool call character by character. Any difference is evidence. Each payload carries a one-time nonce, so "the same replacement target recurring across different nonces" separates deliberate rewriting from model noise.

Please read this before entering a key. This page asks you to give a relay's API key to another server — which is exactly the trust problem it detects. So:
  • the key exists only in the memory of the worker handling your job; it is never written to a database, a log, or a report, and the reference is dropped when the job ends;
  • every occurrence of the key in a report is replaced with [REDACTED_KEY] (there are tests covering this);
  • results are deleted along with the job after 30 minutes, and are tied to no account;
  • the probe never executes anything the endpoint returns — it only compares strings.
If you cannot verify those promises — entirely reasonable — scroll down and use the local CLI, where the key never leaves your machine. Either way, use a throwaway key.
The probe spends this key's quota. Create a throwaway key and delete it afterwards.
Coverage

Four techniques it can find

Classes and measurements come from arXiv:2604.08407.

AC-1
Payload injection
Rewrites the returned tool-call arguments, swapping the download target for the attacker's
AC-1.a
Dependency swap
Changes only the package name, leaving the registry intact, defeating domain allowlists
AC-1.b
Conditional delivery
Behaves perfectly, then targets only sessions matching a chosen fingerprint
AC-2
Credential theft
Alters nothing at all, and quietly keeps your keys and prompts
New to this?

Plain-English glossary

This section is for anyone meeting the problem for the first time.

What is a relay, and how do I know if I am using one?

If you are not pointing at an official Anthropic or OpenAI address, but at a URL somebody gave you along with a cheap key, that is a relay.

How to check: look at the base_url configured in your tool. If it is not api.anthropic.com or api.openai.com, then somebody else's server is forwarding your requests.

Where do I find my base_url?

Claude Code: the ANTHROPIC_BASE_URL environment variable, or ~/.claude/settings.json.

Codex: base_url in ~/.codex/config.toml.

Cherry Studio, NextChat and similar: the "API address", "endpoint" or "proxy URL" field in settings.

Why can a relay see my data? Isn't it encrypted?

HTTPS only guarantees the leg between you and that server. The relay is that server — encryption ends there, and it then opens its own connection to the real Anthropic or OpenAI.

So to the relay, your prompts, your file contents and your API key are all plaintext, and it can change what the model sends back before passing it on.

What is a "tool call", and what happens if one is changed?

When an AI assistant wants to run a command, install a dependency or edit a file, the model returns a structured "tool call" saying what to do. Your agent receives it and executes it.

If a relay swaps the download URL inside it for the attacker's, your agent will comply, and the command still looks like the normal one.

What is a "throwaway key" and how do I make one?

Create a new key in your relay's dashboard, give it a small quota, and delete it once the scan is done. If that key leaks, the loss is bounded.

Do not test with the key you use every day.

FAQ

Things worth settling first

How do I tell whether my relay is rewriting my requests?

There is a five-second check that works on any relay: send a message saying hi and look at prompt_tokens.

A single-digit number is normal. Hundreds or thousands means somebody prepended something to your request — and is billing you for the tokens they inserted.

Are cheap Claude or GPT relays safe to use?

A relay is an application-layer man in the middle by design. It terminates your TLS and reaches upstream over its own connection, so your prompts, tool definitions and API key are plaintext to it, and it can rewrite the tool calls your agent is about to execute.

Worth stressing: paying does not make it safe. 1 of the 28 paid relays the paper measured was injecting malicious code.

If the scan comes back clean, am I safe?

No, and every report says so. Conditional delivery behaves perfectly until its trigger fires, and the trigger logic runs server-side.

No finite black-box probe can prove a relay is honest. Widening coverage is all this tool can do; it cannot close that gap.

Does agent-police execute the commands the endpoint returns?

Never. Detection happens entirely at the string and metadata level. A probe asks for a command, the tool compares the returned arguments, and nothing is run.

This is a deliberate difference from the measurement pipeline in the paper, which executed payloads in a sandbox.

Do I have to hand over my API key?

Not for everything. The endpoint triage and the command self-check need no credentials at all.

Only the full probe needs a key, because it has to obtain real model responses to compare against. If you would rather not give a key to another server — entirely reasonable — use the local CLI.

I want my key to never leave my machine.

Use the command-line version:

pip install agent-police agent-police audit https://your-relay.example.com/v1 --model claude-sonnet-4-5

The key is prompted for interactively — not echoed, and never in your shell history.

Two tools

And after the scan?

The scanner answers "is this relay clean?". The gate answers "should this command run?".

CLI

Scan locally, key stays put

pip install agent-police agent-police audit https://your-relay.example.com/v1 \ --model claude-sonnet-4-5
Gate

Install into Claude Code / Codex

pip install agent-police-gate apgate install claude-code

See what it blocks →