Security
You are considering sending us documents that contain your customers' names, addresses and bank details. This page states precisely what we do with them and how the service is built — including the things we have not done yet.
The strongest guarantee we can offer
If your security review says invoice data must never leave your infrastructure, you do not need to argue with us about our controls — use @stampbench/core locally. It is MIT-licensed, runs offline, has no telemetry, and contains the same rule engine the hosted API uses. The hosted product exists to save you maintenance, not to hold your data.
Invoice data
- ✓Invoice XML sent to the hosted API is processed in memory to produce a validation result and is not written to our database. We store the outcome (valid/invalid, rule counts, timestamp) for your usage metering — not the document.
- ✓Request bodies are capped at 2 MB and every field is schema-validated before it reaches the rule engine.
- ✓The open-source library runs entirely on your own infrastructure. If you never want an invoice to leave your network, use it and never call the API — it is MIT-licensed and has the same rule engine.
XML parsing (XXE and entity attacks)
- ✓Our parser performs no DTD processing and no external-entity resolution, so classic XXE file-disclosure and SSRF-via-entity attacks are structurally absent rather than filtered.
- ✓Billion-laughs style entity-expansion bombs are likewise not applicable, since entity expansion is not performed.
- ✓Non-finite and malformed numeric values are rejected at the API boundary and defensively guarded again in the generator, so they can never be emitted into a document.
Credentials & sessions
- ✓Passwords are hashed with PBKDF2-HMAC-SHA256 at 100,000 iterations (WebCrypto), each with its own random 16-byte salt. Plaintext passwords are never stored or logged.
- ✓API keys are generated from 20 bytes of cryptographic randomness, stored only as a SHA-256 hash, and displayed exactly once at creation. We cannot recover a lost key — you rotate it.
- ✓Revoking a key takes effect immediately: revoked or unrecognised credentials return 401 and are never silently downgraded to anonymous access.
- ✓Sessions are stateless HS256 JWTs carried in an HttpOnly, SameSite=Lax, Secure cookie and signed with a server-side secret, so a session cookie cannot be forged or altered without it. A separate readable, non-secret flag lets the site skip a server round-trip for signed-out visitors and carries no session token.
- ✓Login and registration are rate-limited per IP, and authentication runs a constant-time comparison against a dummy credential even when the account does not exist, so response timing does not reveal which emails are registered.
Application & transport
- ✓HTTPS everywhere, enforced by the hosting platform.
- ✓Security headers on every response: a Content-Security-Policy restricting script and connection sources, X-Frame-Options: DENY, X-Content-Type-Options: nosniff, a strict Referrer-Policy, and a Permissions-Policy disabling camera, microphone and geolocation.
- ✓Database access goes exclusively through parameterised prepared statements (Cloudflare D1); no string-concatenated SQL exists in the codebase.
- ✓Per-key and per-IP rate limiting plus monthly quotas, so a leaked key has a bounded blast radius.
- ✓Billing webhooks are verified by cryptographic signature — PayPal subscription events today, and Stripe if card billing is enabled — and unsigned or mis-signed payloads are rejected before any account state changes.
- ✓The optional inbound payment webhook (auto-invoicing) is authenticated by a secret URL you can rotate, is rate-limited, and can only create draft invoices or mark your own invoices paid — never move money or read data back. Auto-created invoices are held in their own archive so they can never displace the invoices you saved yourself.
- ✓Structured JSON logging that records outcomes and never request bodies, credentials or invoice contents.
Development practice
- ✓394 automated tests run across the library, CLI and web app, including regression tests for the specific validation bugs we have previously fixed.
- ✓The codebase passed a multi-agent adversarial security review in which every finding had to survive a second reviewer attempting to refute it; all high-severity findings were remediated before launch.
- ✓Dependencies are deliberately few. The rule engine has two runtime dependencies.
AI features
Three optional features send data to Anthropic's API, and only when you use them. Explain this error sends the validation findings — rule identifiers, business terms and our own message text. AI assist in the invoice builder sends only the free-text description you type into that box. The assistant (paid plans) sends the messages you type into the chat. None of them is ever sent your full invoice, a VAT identifier or a payment detail unless you type it yourself. Each is opt-in, size-capped and metered; validation and generation never call Anthropic at all. If your data-processing policy does not permit a sub-processor, simply do not use these features.
What we have not done yet
- —SOC 2 Type II or ISO 27001 certification. We do not have either, and we will not imply otherwise.
- —A signed DPA/AVV and a formal EU-data-residency commitment — in progress for the Platform tier; ask us for current status before relying on it.
- —A third-party penetration test. Our review was internal and adversarial, but it was not an external pentest.
- —A published uptime SLA. The service is new; we would rather commit to a number we have history for.
Reporting a vulnerability
If you believe you have found a security issue, please report it privately to [email protected] before disclosing it publicly. Include enough detail to reproduce the issue.
- • We aim to acknowledge reports within 3 working days.
- • We will keep you updated while we investigate and tell you when it is fixed.
- • We will credit you when a fix ships, unless you prefer otherwise.
- • We will not pursue legal action against good-faith research that respects user privacy and avoids service disruption or data destruction.
Please do not run automated scanners against the production API — use the open-source library locally instead, where you can test freely.
See also: test evidence · privacy policy · terms