Security at Permenta
We keep other people’s product-security records, so we publish our own: how to report a vulnerability to us, how the service is built and run, and who processes data on our behalf.
Reporting a vulnerability
Our coordinated vulnerability disclosure policy. It is the policy our security.txt file points to, and the same kind of policy Permenta generates for its customers.
If you believe you have found a security problem in Permenta, write to security@permenta.com. Plain email is fine; if you need to send something encrypted, ask for a key in your first message. Please include the affected address or component, the steps to reproduce, what you think the impact is, and how you would like to be credited.
What we will do
- Acknowledge your report within 2 business days, with a reference you can quote.
- Confirm the problem, rate its severity and tell you what we intend to do; we keep you informed while we work on it.
- Fix it, roll the fix out, and inform affected customers where that is needed.
- Publish an advisory once the fix is available and credit you in it if you wish.
Coordinated disclosure
We ask you to give us up to 90 days from your report before you publish details. If the fix ships earlier, we will agree an earlier date with you; if we need longer, for example because a third-party component is involved, we will tell you why and ask for an extension rather than assume one.
In scope
permenta.com, app.permenta.com, the API and this policy itself. Out of scope: volumetric denial of service, social engineering of staff or customers, physical attacks, findings that require an already compromised device or account, reports generated by automated scanners without a demonstrated impact, and the services of our subprocessors except as we integrate them.
Rules of engagement and safe harbour
Use test accounts, stop at the point of proof, do not access, change or delete data that is not yours, and do not disrupt the service for others. We will not pursue or support legal action against anyone who researches in good faith within this policy, and we regard such research as authorised to the extent we can grant that authorisation.
Machine-readable contact details are published at /.well-known/security.txt (RFC 9116).
How Permenta is built and run
The controls behind the service, in the order someone attacking it would meet them. The threat model behind this list is a living document we revisit with every new integration.
Hosted in the EU
Permenta runs on Microsoft Azure in the Sweden Central region: the application, the PostgreSQL database, blob storage, secrets and backups sit in one EU region, described as infrastructure code and deployed from CI with short-lived credentials.
Azure region Sweden Central (EU); no routine data transfer outside the EU.
Tenant isolation in the database
Every tenant table carries the workspace id and PostgreSQL row-level security is forced on it. The application sets the workspace for each transaction and the database refuses rows from any other; integration tests try cross-tenant reads and writes on every change.
Row-level security with FORCE on every tenant table.
A separate realm for staff
Internal staff sign in to a separate admin portal on its own origin, with passkeys only, from an IP allow-list and with step-up for sensitive actions. Their database role can only read tenant data, and every staff action is appended to a hash-chained audit log.
Separate origin, cookie, database role and audit ledger; admins are not users.
Hash-chained ledgers
Evidence ledgers and the staff audit log are append-only: triggers and revoked privileges prevent updates and deletes, and each entry carries the hash of the one before it, so a gap or an edit is detectable. Uploaded files are stored with versioning.
Append-only tables, hash chains, versioned blob storage.
Encryption in transit and at rest
TLS on every connection, including between the application and the database, and platform-managed encryption at rest for the database, its backups and blob storage.
TLS everywhere; encryption at rest by the platform.
Least-privilege roles
Four database roles, migrator, web, worker and admin, hold only the rights each needs; secrets live in a key vault and are read through managed identity; background work runs in a separate worker process with its own role.
No shared credentials; no secrets in the repository.
Authentication built against account takeover
Email verification, a breached-password check, database-backed rate limits, and passkeys and one-time codes available to every account. Sessions are cookies the browser’s scripts cannot read.
Passkeys and TOTP on every plan.
Content security policy
Every page is served with a per-request nonce content security policy without inline scripts, a frame-ancestors restriction and the usual security headers, so a markup injection cannot run code.
Nonce CSP, no unsafe-inline, frame-ancestors none.
Dependency scanning and supply chain
Dependencies are pinned through a locked catalogue with a release-age gate, scanned automatically, and Permenta publishes its own SBOM: we ask our customers to do it, so we do it too.
Frozen lockfile, release-age gate, dependency scanning, published SBOM.
SHA-pinned CI and reviewed deploys
Every CI action is pinned to a commit hash, deploys use OIDC federation instead of stored cloud credentials, migrations run as a separate job before new code goes live, and production deploys require a reviewer.
SHA-pinned GitHub Actions, OIDC, reviewed production releases.
Uploads treated as hostile
SBOM uploads are streamed with size limits, XML entities disabled and caps on components and nesting, parsed in the worker rather than the web process, and stored under keys the server chooses.
Streaming limits, entity expansion disabled, server-generated storage keys.
Backups and recovery
The production database keeps point-in-time restore for 35 days, migrations are forward-only and backward compatible with the running code, and the rollback procedure is written down and rehearsed.
35-day point-in-time restore; documented rollback.
Subprocessors
The third parties that process data on our behalf. A data processing agreement with this list as its annex is available on request.
| Subprocessor | Purpose | Data | Location |
|---|---|---|---|
| Microsoft Azure | Hosting: application containers, the PostgreSQL database, blob storage, secrets, logs and backups. | All account and workspace data. | European Union (Azure region Sweden Central). |
| Stripe | Payments, invoicing, tax calculation and the billing portal. | Billing contact, company name and address, VAT ID and the payment method. Card numbers never reach Permenta. | European Union and United States. |
| Resend | Transactional email: verification, invitations, reporting-deadline reminders and account notices. | Recipient name, email address and the content of the message. | European Union data region; the provider is established in the United States. |
To request the data processing agreement, write to privacy@permenta.com. The current text is published at /legal/dpa.
Documents and contacts
Everything on this page has a permanent address, so customers and their auditors can link to it.
- security.txt (RFC 9116)
- Coordinated vulnerability disclosure policy
- Subprocessors
- Data processing agreement
- Privacy policy
- Changelog, including the regulatory catalogue version
Security questions that are not vulnerability reports: hello@permenta.com.