Skip to content
New kind of attack — caught and fixed before it was publicly known·Read the timeline
Proof

Don't trust the verdict. Re-verify it.

Every verdict is a signed file. Your browser re-checks the Ed25519 signature from the raw bytes — change one byte and it stops verifying. No Probity server, no account. Back to the overview →

Verify it yourself

The same check runs anywhere — not just in this page.

The verifier is free and open. Re-check any Trust Receipt from your terminal or your CI, against the public key we publish at /.well-known/verification-keys.json. You pin the key; you never have to trust us.

Your terminal
# the open verifier, the pinned key and a real signed verdict
curl -sO https://getprobity.dev/verify/probity-verify.py
curl -sO https://getprobity.dev/verify/probity.pub
curl -sO https://getprobity.dev/verify-mcp/scorecard.catch.intoto.jsonl
pip install cryptography
python3 probity-verify.py scorecard.catch.intoto.jsonl probity.pub
# → PASS: the statement is VALID · result: fail
Your CI
# block a merge unless the receipt re-verifies (exit 1 fails the job)
- run: |
    curl -sO https://getprobity.dev/verify/probity-verify.py
    curl -sO https://getprobity.dev/verify/probity.pub
    pip install cryptography
    python3 probity-verify.py scorecard.intoto.jsonl probity.pub
The Trust Receipts

Every Trust Receipt on this site is a real, downloadable file.

These aren't screenshots — each link is the literal signed file the gate emitted. Download one and run the verifier above: it passes or fails on the math, in your hands.

How the check works

Why a tampered Trust Receipt can't survive.

In plain English

The Trust Receipt is sealed with a private key only Probity holds. Anyone can check it with the matching public key; no one can forge or edit it without the private one. Change a single character and the check fails. A green you can re-check yourself can't be faked — even by us.

For engineers

Each bundle is a DSSE / in-toto envelope. The signature is Ed25519 over the RFC 8785 (JCS) canonical PAE pre-image, domain-separated per payload type, against a pinned raw-key keyid (427a1092…). Verification is pure WebCrypto in the browser, or offline via the standalone Python verifier at /verify/probity-verify.py — a second, independent implementation of the same check. An unknown predicate type fails outright — nothing falls through to a default. Published signed known-bad bundles let you confirm every implementation rejects exactly the same things. Re-check any of it on a fully air-gapped laptop: no Probity software, no network.

Read the full predicate standard →
The four outcomes a check reaches
  • FAILA blocking-tier attack got through; the build stops. Some row's containment was a caught label, a label outside the carried vocabulary, or a missing or unrecognized basis or method — fail-closed, never silently dropped.
  • DEGRADEDIt ran and held, but a check couldn't complete. Coverage was incomplete — something was out of scope or routed elsewhere. We report incomplete rather than fake a green.
  • PASS · INDIRECTPassed, but at least one clean result rests on indirect evidence. A clean row declared a basis other than the substrate (the artifact's own account of itself) or a method other than intercepted (reconstructed after the fact, not caught live).
  • PASSNo findings at the severities your policy blocks. Every clean row rested on a direct, live interception at the substrate. It proves what we tested, not that the agent is “safe.”

The separation is the point: the producer signs, any third party checks. You can't grade your own homework, and neither can we.

Re-verify it here

Re-verify any of them, live in your browser.

Eleven real signed verdicts — a caught exfiltration, an A2A escalation, a dormant logic bomb, an honest “degraded”, and a tamper test that breaks the instant you flip a byte. Click any one and re-check its Ed25519 signature with WebCrypto, from the raw bytes.

Every tab is a real signed bundle, one signature scheme — re-check any of them in your browser · what PASS / DEGRADED / FAIL mean →

Caught before it ever ran — no VM needed.

Start cheap: the static scan reads the server's declared surface and flags the dangerous tools without booting a thing. It's a prediction — and it's already a signed artifact the box will go on to prove.

verifiedCAUGHTverdict: fail

Signature checks out. Caught it. Contained it. Signed it.

A real Trust Receipt · re-checkable offline, no Probity server.

Don't trust us — click to re-check this Ed25519 signature in your own browser.

Clean vs caught vs couldn't-run

The gate tells clean from caught from couldn't-run.

We ran 15 real, well-known MCP servers through the box. Clean means well-behaved — good servers, nothing to catch (not exploits we found in them). Caught means the server was handed a decoy credential, sent it to its own API — and the box captured it on the way out (a behaviour we induced, not a vulnerability we found). Couldn't-run means the gate refuses to fake a pass for what it can't boot.

9 Clean3 Caught3 Couldn't run
  • filesystemClean

    ran the full attack suite in the box — well-behaved, nothing to catch

  • slackCaught

    given a decoy token, the box captured its outbound credential on the way out

  • fetchClean

    ran clean in the box — it behaves

  • gitCouldn't run

    couldn't boot in the sealed image — the gate signs DEGRADED, never a faked pass

  • memoryClean

    ran clean in the box — it behaves

  • google-mapsCaught

    given a fake key, the box captured its outbound credential

  • sequentialthinkingClean

    ran clean in the box — it behaves

  • githubCouldn't run

    couldn't boot in the sealed image — the gate signs DEGRADED, never a faked pass

  • everythingClean

    ran clean in the box — it behaves

  • brave-searchCaught

    given a fake key, the box captured its outbound credential

  • postgresClean

    ran clean in the box — it behaves

  • sentryCouldn't run

    couldn't boot in the sealed image — the gate signs DEGRADED, never a faked pass

  • puppeteerClean

    ran clean in the box — it behaves

  • sqliteClean

    ran clean in the box — it behaves

  • timeClean

    ran clean in the box — it behaves

Now put it in front of your own agent.

You have re-verified ours. Request access and run the Gate on a server you actually ship.

See how it works →
Get access

Run your agents through Probity.

A few details about your setup and we'll get you gating agents fast.