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
squidbrakein 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 (likerm) 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 withsquidbrake telemetry off,SQUIDBRAKE_TELEMETRY=0orDO_NOT_TRACK=1;squidbrake telemetry statusshows 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 --keychecks 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
- Single sign-on (SAML or OIDC) for the dashboard. People sign in with their own key.
- Choosing the region where a hosted dashboard keeps data. Self-host to decide that yourself.
- An uptime guarantee (SLA) for hosted dashboards.
- A console for service providers managing agents across many client companies.
- Undo copies for MCP tools: their changes can't be copied from outside the tool, so a rule that requires a copy blocks them, and held ones run without one (the record says so).
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:
- Paths you didn't connect. An agent with its own unguarded shell, credentials or network access can act outside it. Connect every tool path; lockdown makes the agents' managed settings require it.
- Harm hidden inside a tool. A compromised MCP server can add a side effect after a person approves the visible call, like a hidden BCC. No gateway in front of the tool can see that; it's in our incident replays as not stopped.
- A person who says yes. A hold makes sure someone sees the action and the reason. It can't make them read it.
- Hosted apps that only sign in through a browser. Slack, HubSpot and other OAuth-only MCP servers can't be connected by URL yet.
- An agent built to attack you. It's designed for the common case: a cooperative agent that makes a mistake or follows instructions it read somewhere. For an agent you don't trust at all, run it in a sandbox too.
Where it helps with compliance
Squidbrake produces evidence for controls like these. It supports your evidence; your auditor decides what it satisfies.
| Control | What 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.