A product used to prove compliance has to survive its own review
What follows is the detail a security team will ask for during procurement, including the parts that are still in progress. A page that claimed everything was finished would not be worth reading.
Tenant isolation
Every record belonging to a customer carries a tenant identifier, and isolation is applied automatically by the data layer to every entity that carries one rather than being written into each query by hand. A query that forgets its tenant predicate returns nothing; it cannot return somebody else's data.
The tenant comes from a claim inside the signed authentication cookie, never from a header or parameter a caller controls, and the membership is re-checked against the database on every request, so revoking access takes effect immediately rather than when a cookie eventually expires. An existing record is prevented from moving between tenants at the persistence layer.
Authentication and access
- Passwords require twelve characters minimum, with lockout after eight failed attempts. Length is favoured over character-class rules, which mostly produce predictable substitutions.
- Roles are coarse and ordered, so an access review is tractable: a reviewer reads eight role names, not a permission matrix.
- External auditor access is time-boxed and lapses automatically rather than relying on somebody remembering to revoke it.
- Single sign-on is available on Enterprise.
- API keys are stored hashed. Verification is a constant-time comparison, and each key carries explicit scopes, so a read key cannot write.
Payment data
Card details never reach our servers. Checkout and payment method management both happen on Stripe-hosted pages, which keeps the service out of PCI DSS scope beyond the simplest self-assessment. We store a customer reference and a copy of your invoices, nothing more.
The audit trail
Every change to risk, control, and evidence data is recorded, along with authentication events, with the actor, address, and a diff of what changed. Entries are append-only; application code cannot update or delete them, and retention pruning is the only process that removes anything.
Fields whose names indicate a secret are redacted before the diff is written, because the trail is widely readable inside a tenant and a change record is an easy way to leak a credential.
Evidence integrity
Uploaded evidence is hashed with SHA-256 at the point of collection, so you can demonstrate an artefact has not been altered since. Storage keys are generated by the platform and namespaced by tenant; an uploaded filename is never used as a path. Every file access is checked against the canonical resolved path, so a crafted key cannot escape the tenant's own directory.
Application hardening
- A content security policy restricting scripts to our own origin. No third-party script runs on any page, including analytics.
- Framing refused outright, so the risk acceptance controls cannot be clickjacked.
- Antiforgery protection on every state-changing form.
- Webhooks are signature-verified before the payload is parsed, and are refused entirely if no signing secret is configured rather than degrading to trusting the sender.
- Only site-relative return URLs are honoured after sign-in, so the flow cannot be used as an open redirect.
- Uploaded XML is parsed with entity resolution disabled, so a malicious scanner export cannot become a server-side request forgery.
- Encryption keys are persisted in the database, not the container filesystem, so a redeploy cannot silently invalidate sessions or stored credentials.
The built-in network scanner
Disabled by default on hosted deployments, and deliberately so. A scanner in shared hosting that probes whatever address it is given is a port-scanning service operating under somebody else's address space.
Where it is enabled it refuses loopback, link-local, multicast, and the cloud instance metadata endpoint, and will not touch public addresses without a second explicit setting. It performs discovery only: TCP connect and a banner read. It does not attempt authentication or send exploit payloads.
What we have not finished
Stated plainly, because you will find out during procurement anyway and it is better to hear it now.
- No SOC 2 report yet. We have not completed an independent audit. If your procurement process requires one, tell us and we will tell you honestly where we are.
- No published penetration test. Planned before general availability.
- Single region. Data residency options beyond our primary region are available on a Custom plan only.
- Encryption at rest is provided by the managed database, not by application-level field encryption. Sensitive connector credentials are additionally encrypted before storage.
Reporting a vulnerability
If you find a security issue in this product, please tell us at [email protected]. We will acknowledge within two working days and keep you informed until it is resolved. We will not pursue legal action against anyone acting in good faith under a coordinated disclosure.