Security

The security model, plainly

No product is unbreakable, and Verfy does not claim to be. This page says what Verfy protects, how, and where its protection ends. The full threat model is in docs/THREAT_MODEL.md in the repository.

proves A receipt shows

  • which tool call passed through Verfy, when, and in which session;
  • the verdict, the rules that fired and the hash of the policy that decided it;
  • the digest of the tool definition in use, and a salted hash of the arguments and result, so nobody can guess them from the receipt;
  • that the device holding the key signed it, and that no receipt in the chain was changed, removed or reordered since.

does not prove A receipt cannot show

  • what a tool or MCP server did internally after it was called;
  • actions that never went through the Verfy hook or gateway;
  • that the device itself was not compromised when it signed;
  • that a whole ledger was not deleted and restarted, or rebuilt and re-signed by someone holding the device key (only an outside copy, such as the receipts already synced to Verfy Cloud, shows that).

Controls in place

Tenant isolation

Row-level security on every table, keyed to the signed-in user's memberships. Server routes check the organization again. Cross-tenant access is covered by automated tests on real Postgres.

No direct writes

Browsers can only read. Every change goes through a database function that checks the caller's role and writes an audit entry in the same transaction.

Append-only evidence

Receipts, published policy versions and the audit log cannot be updated or deleted, not even with the server's secret key.

Device keys

Receipts are signed on the device with Ed25519. The server stores only public keys and re-verifies every signature and hash link on upload.

Secrets

The secret Supabase key is used only in server code after Verfy has authenticated the caller. Device tokens and invitation tokens are stored as SHA-256 hashes.

Operator access

Verfy's operator has one read-only page listing accounts, organizations and the waitlist (no receipt contents or policies). It opens only for the operator's account after a second factor; everyone else gets a 404, and every view is recorded in an append-only log before anything is read.

Web hardening

A CSP with no inline script it does not name (a per-request nonce on signed-in pages, a SHA-256 for each script on the public pages), HSTS, frame blocking, strict referrer policy, origin checks on every cookie-authenticated change, schema validation with size limits, and safe error messages.

Rate limits

Shared Postgres counters across serverless instances for sign-in, enrollment, ingest, exports and public endpoints. If the limiter fails, requests are refused, not let through.

Supply chain

Pinned dependencies with a lockfile, dependency audit and secret scanning in CI, and a CLI with no required third-party packages.

Can the agent switch Verfy off?

We tried the obvious ways. Verfy blocks the agent from editing its hook settings, its lock, its policy or its install, and from approving a tool change for itself. It cannot follow a program the agent writes to a file and then runs: that program can still change the settings. Verfy also cannot notice from inside the computer that its hook was removed, because a removed hook does not run; on a team, the device simply stops sending receipts. Checking the settings again at session start would not change this, since that check would live in the same settings file.

Attempts to switch Verfy off and what Verfy answers
What the agent triesVerdictRule
Edit ~/.claude/settings.json to remove the hookdenyVFY-SELF-001
printf '{}' > .claude/settings.jsondenyVFY-SELF-001
rm ~/.claude/settings.jsondenyVFY-SELF-001
verfy lock approve filesystem --yesdenyVFY-SELF-003
pip uninstall -y verfydenyVFY-SELF-004
Edit .mcp.json to take a server off the gatewayaskVFY-SELF-002
python -c "open('.claude/settings.json','w').write('{}')"askVFY-SELF-005
cat ~/.verfy/key.json (the signing key)denyVFY-SELF-006
Read ~/.verfy/team.json (the device token)denyVFY-SELF-006
Write fix.py, then run python fix.pyallownot followed

Known limits

  • Guard rules are pattern matching. A determined attacker can phrase a command Verfy does not recognise; unknown risky patterns are not assumed safe, but Verfy is not a sandbox.
  • The scanner finds known warning signs. A clean scan does not mean a tool is safe.
  • DDoS protection depends on your hosting plan and settings. Verfy adds application rate limits; it does not replace a firewall.
  • No independent penetration test has been performed yet. Treat this release as an MVP and review it before relying on it.

Find a bypass

Verfy has not had a professional penetration test yet, so we ask everyone to try to break it: a command, path, URL or tool call that should be denied or asked about but is allowed, a way for an agent to switch Verfy off, a changed MCP tool that gets past the gateway, or an edited receipt chain that still verifies. verfy check "…" shows the verdict without running anything.

Report it privately (below). With your permission, everyone who finds a valid bypass is listed in the hall of fame and credited in the release notes. Known limits, such as a script the agent writes and then runs, are listed above and are not bypasses.

Report a vulnerability

Please report security issues privately, not in public issues. Use GitHub's private vulnerability reporting on the Verfy repository (Security tab, "Report a vulnerability": open the form). A way for an agent to get past Verfy counts as a vulnerability too. Include steps to reproduce and the version you tested. We will acknowledge your report and keep you informed while we fix it.

Please do not test against other people's deployments, access data that is not yours, or degrade service for others.