squidbrake

Security

What it sees, what it keeps, what it can't stop.

Squidbrake sits between AI agents and the actions they take, so it has to be the most boring, most checkable part of your stack. Everything below can be checked in the source.

Where it runs and where your data goes

Self-hosted: your data stays with you
On a laptop, in Docker, or on your own server. Tool calls, results, decisions and the audit trail are in your database (SQLite or Postgres) and nowhere else.
Hosted dashboards, for pilots
We run the gateway for you on a server we operate. It stores the same things, there. If it has to stay inside your network, self-host it: it's the same software.
It fails closed, rule by rule
If an agent can't reach Squidbrake, its tool calls don't run. Each rule can say otherwise (when_unreachable: allow, say for reads), and agents keep a copy of those answers so they follow them while it's down. What runs then isn't recorded, so allow only what you'd accept unrecorded.
Usage stats, and how to say no
The first time you run squidbrake in a terminal, it asks once whether to send anonymous usage stats; pressing Enter means yes. Sent: a random id, the command name (never its arguments), version, operating system, CPU type, Python version, country, counts of what was allowed, held and blocked, and for each held or blocked action the program (like rm) and the rule. Never sent: commands an agent ran, file names or contents, prompts, rules, keys, the audit trail. Agent hooks send nothing. Turn it off any time with squidbrake telemetry off, SQUIDBRAKE_TELEMETRY=0 or DO_NOT_TRACK=1; squidbrake telemetry status shows exactly what is sent.

Secrets and keys

Secrets are redacted before anything is stored
Rules see the call as it is; storage only ever gets a redacted copy. Fields named like passwords, tokens, API keys, authorization or cookies are replaced, and so are known secret formats anywhere in the text: GitHub, Stripe, AWS, Slack, OpenAI and Anthropic, Google and npm keys, JWTs, private keys, and passwords inside URLs.
People's details are masked too
Email addresses keep their first letter and their domain plus a short fingerprint (so "the same customer again" is still seen); card numbers keep their last four digits. Lists, phone pages, notifications and AI briefs show at most 2 KB of any value.
Keys are stored as hashes
Every person and every agent has its own key. Only its SHA-256 hash is kept; the key itself is shown once. Removing a key stops it at once.
Agents can't approve
Agent keys can only ask and report. A key never approves its own request, and with second-person approval on, nobody approves what their own agent asked for.
Owners, admins, approvers, viewers
Viewers see and change nothing; approvers decide and can stop agents; admins manage the team and settings; only owners make admins and owners, and a team always keeps one.
Apps' tokens stay on the gateway
When you connect an app's MCP server in the dashboard, its token is kept on the gateway and never shown again, in the dashboard or the API.

Decisions you can check

No model decides
Decisions come from your rules, a shell command reader and the agent's recent history. The same call gets the same answer every time, and every answer names the rule that made it. The optional AI brief on a held action is advice for the person deciding: it runs on your own Anthropic key, is sent only what the dashboard shows (redacted), and nothing reads it to decide. With no key set, nothing is sent.
A tamper-evident audit trail
Every decision, approval and settings change is hash-chained: editing or deleting a past entry breaks every hash after it. Anyone can verify an exported trail offline with squidbrake verify FILE. Every version of your rules that made a decision is kept with it.
Signed checkpoints
Every 50 entries the chain's fingerprint is signed (Ed25519) with the gateway's ledger key. Its public half is published at /v1/audit/public-key; verify.py --key checks an export against it, so even someone who can write to the database can't quietly rewrite history and re-chain it.
Approvals signed by a device
Register a phone or laptop as a passkey and each approval is signed by it with Face ID or fingerprint, over exactly which action was approved. The signature is kept in the audit trail and checked offline by verify.py. You can require it for every approval.
Approval links are signed
The one-tap links in Slack, Discord and phone notifications are signed (HMAC-SHA256) for one action and one approver, and stop working once it's decided or expires.

What's stored

On every action
The tool, its input and result (redacted), who asked, the decision and the rule behind it, who approved and when, and the risk notes the checks found.
Undo copies
Before a held or irreversible action runs, a copy of what it changes: files and git changes stay on the agent's own computer (squidbrake undo); for API calls through Squidbrake and for your own snapshot functions, the record is kept on the gateway, redacted like everything else. If a copy is required and can't be made, the action doesn't run.
Spend and proof
Model token counts agents report (for spend limits), and the answer of each proof check (it looks in Stripe, GitHub or your database with credentials that live only in the gateway's environment, and only reads).
Devices
For each passkey: its public key, its name and who registered it. Never a fingerprint or face: those never leave the device.

What isn't built yet

Certifications

We hold none today: no SOC 2 report, no ISO 27001 certificate. Squidbrake gives you evidence for your own audits; it doesn't make us, or you, certified. We'll say so here when that changes.

The software itself

Published by CI, not from a laptop
PyPI releases are built and published by GitHub Actions with PyPI trusted publishing, so no upload token exists anywhere, and each release carries a provenance attestation. The Docker image is built by GitHub Actions too.
Tested on every change
Hundreds of tests run on Linux, macOS and Windows, on three Python versions, for every change. So do the replays of public incidents and a benchmark against normal permissions.

What it can't stop

Squidbrake guards what goes through it. Know where that ends:

Where it helps with compliance

Squidbrake produces evidence for controls like these. It supports your evidence; your auditor decides what it satisfies.

ControlWhat Squidbrake gives you
SOC 2 CC8.1
Change management
Changes an agent makes are authorized by a rule or approved by a person, with who approved what and when, in a tamper-evident log and a one-page evidence pack.
ISO/IEC 27001:2022 A.8.32
Change management
The same record of who approved each change, against a versioned policy file.
ISO/IEC 27001:2022 A.8.15
Logging
Every tool call, decision and approval logged, hash-chained, exportable as CSV or JSONL and verifiable offline.
EU AI Act Art. 14
Human oversight, high-risk systems
A person can see, hold, reject and stop an agent's actions: one action, one session, or every agent.
ISO/IEC 42001
AI management system
Records of what each AI agent did and who approved it, protected by signed checkpoints, with an evidence pack mapped to its controls.
EU AI Act Art. 12
Record-keeping, high-risk systems
Automatic logs of what the agent did and why each action was allowed, held or blocked.

Reporting a vulnerability

Please don't open a public issue. Email it privately to hello@squidbrake.com. You'll hear back within a few days. Especially interesting: a way to run something a rule blocks or holds, approving without an approver key, secrets stored unredacted, or rewriting the audit trail without the check noticing.