Anvil. Back to home
v1.2 · Effective 2026-11-04

This is Anvil’s current public statement. Where a signed Master Services Agreement or Data Processing Addendum differs from this page, the signed agreement governs. If you need a signed DPA, email henry@anvilcontrol.ai — the DPA page says exactly where we stand on producing one.

Security policy

Anvil sits on the money path. A defect here does not corrupt a dashboard — it lets an agent double-charge a customer, or blocks a payment that should have gone through. We would much rather hear about it from you than from a customer.

This page serves two readers. If you are evaluating Anvil, start with "What protects your data" below. If you are reporting a vulnerability, skip to reporting — and please do not open a public issue for it.

What protects your data

Stated as implemented, not aspirational. Anvil is operated by one person; where a control is small or absent, this table says so rather than borrowing the vocabulary of a larger company. The contractual version of the same list is section 5 of the DPA.

ControlWhere it stands today
Encryption in transitTLS on every hosted surface, HSTS in production.
Encryption at restProvided by our host for the Postgres database and Redis, and by GitHub for the daily backup artifact.
Tenant isolationEvery tenant-scoped read and write is filtered by workspace at the query layer. An automated check fails the build on a raw un-namespaced key, and a two-tenant end-to-end test proves one workspace cannot reach another's policies, receipts, spend counters, or approvals. This is the class of bug we care about most.
AuthenticationGoogle OAuth for the control plane; hashed API keys for the runtime API. Reads and the interface fail closed in production when no control token is configured.
Authorisation for high-risk actionsMaker-checker approvals with self-approval blocked. An override requires an armed, single-use token and is recorded against the operator who used it.
Credential storageAPI keys are stored as hashes with a non-secret prefix and are not recoverable from the database. Connector credentials are held in memory only. Webhook signing secrets are stored in cleartext because the server is the signer and needs the value to compute the HMAC — see the DPA for why hashing is not available there.
Audit recordsA decision record for every guarded call, linkable into a tamper-evident hash chain that anvil verify checks. HMAC signing of that chain is off unless a signing key is configured, and the product labels the unsigned state honestly rather than implying attestation.
DurabilityMoney-path execution truth is written to Postgres *before* the action, so a crash cannot lose the record that made double-execution possible. The service refuses to boot in production on undeclared ephemeral storage.
Backups and recoveryA daily pg_dump that is restored into an empty database and row-count-verified in the same run — a dump that does not restore fails that day's job, loudly. Kept 14 days as a private build artifact. Our host does not offer native Postgres backups on our plan, which is why this exists. Recovery is a manual restore by one operator; there is no documented RTO/RPO, no second region, and no automatic failover.
Secure developmentEvery change goes through pull-request review, a typed build, and a test suite that gates deploys. A security fix ships with a regression test that fails on the vulnerable code.
Dependency managementAutomated dependency audit in the pipeline.
Production accessOne person, through individually authenticated accounts at the host, the source host, and the identity provider. No shared logins. Administrative actions in the product are attributed to the operator who took them.
Personnel programmeNone. No background checks, security training, or offboarding process, because there is nobody to run them on. This row changes when the team does.
Independent assessmentNone today. No SOC 2, no ISO 27001, no completed third-party penetration test. If one is a requirement for you, tell us and we will tell you honestly where we are.
Data locationUnited States. No EU or UK data residency option.

Two things worth saying out loud. The backup row is the strongest control here — a restore that is proven every day is rarer than a compliance badge, and it is the one that would actually save your data. The independent-assessment row is the weakest, and we are not going to dress it up: there is no audit report to send you.

Reporting a vulnerability

Email henry@anvilcontrol.ai with SECURITY in the subject line. A human reads that inbox every business day.

Include whatever you have — we will work with a one-line hunch:

If you need encryption before you will send details, say so in a first email with no details and we will arrange a channel.

What we commit to

StageCommitment
Acknowledgement1 business day — a human reply, not an autoresponder
Triage + severity3 business days — we tell you our severity call and our planned fix window
Fix for critical7 days target for anything that lets money move incorrectly, crosses a tenant boundary, or exposes credentials
Fix for high / medium30 / 90 days target
DisclosureCoordinated. We will tell you when the fix ships, and we are happy to credit you by name or stay quiet — your call

If we are going to miss one of those windows we will tell you before it passes rather than after. During beta, "1 business day" has in practice meant same-day.

Safe harbour

We will not pursue or support legal action against you for good-faith security research that:

We do not run a paid bounty programme today. We are a small team and we will say so honestly rather than imply a reward that does not exist. We will credit you, and we will tell you exactly what we changed.

Scope

In scope

Report classes we care about most, in order: tenant-boundary escapes (one workspace reading or writing another's policies, receipts, spend counters, or approvals); anything that makes an enforce-mode guard fail open silently; idempotency/dedup bypass (the double-charge window); credential exposure (API keys, install tokens, connector credentials, ANVIL_CP_AUTH_SECRET handoff tokens, ANVIL_METRICS_TOKEN); authentication or approval bypass, including self-approval of a maker-checker gate; audit-record forgery or hash-chain tampering.

Out of scope

Which versions we fix

SurfaceSupported
@useanvil/sdkThe current latest on npm, and the previous minor for critical fixes
Hosted planesAlways current — there is one deploy, and we patch it

Every guard call the SDK makes arrives with an x-anvil-sdk-version header, so when a fix ships we can identify which tenants are still running an affected client and reach out directly instead of hoping they read a changelog. If you report something that only affects an old client, we will tell you what fraction of live traffic it still describes.

Data handling in the ghost intake

Because it shapes what a report about it means, here is what the intake actually does. The customer-facing version of this is on the intake screen itself and at anvilcontrol.ai/privacy.

Fixes you will see from us

When we ship a security fix we will: name it in CHANGELOG.md, add a regression test in tests/ that fails on the vulnerable code, and — if it touched the money path — say in the changelog entry whether any tenant's money could have moved incorrectly. If the answer is yes, affected tenants hear from us before the changelog does.

For customers under a signed agreement

This page is the public channel and applies to everyone. If you have a signed MSA/DPA with us, the notification, breach, and remediation obligations in that agreement control where they differ from the commitments above — they are stricter, not looser.

What changed in v1.2

Superseded versions remain in our public source history, so a change to this page is something you can check rather than take on trust.