Per-Tenant Encryption and BYOK: How Pentestas Handles Your Sensitive Findings
Pentestas Team
Security Analyst

One master key. One Fernet key per tenant. BYOK swap on Enterprise. No cross-tenant decryption.
This post is the engineering-level answer to "how exactly do you handle our data" — the question every InfoSec team asks before they'll sign the MSA.
In Detail
The data-sensitivity model
A Pentestas scan produces multiple data classes, each handled differently:
| Class | Sensitivity | At-rest protection |
|---|---|---|
| Target URL | Low | Not encrypted (needed for dashboard search) |
| Scan config | Medium | Fernet-encrypted with tenant key (secrets stripped pre-persist) |
| Finding title / severity / CVSS | Low | Not encrypted (needed for dashboard filter) |
| Finding evidence (request + response) | High | Fernet-encrypted with tenant key |
| AI narrative / impact / remediation | High | Fernet-encrypted with tenant key |
| Payload used | High | Fernet-encrypted with tenant key |
| Stored credentials (Azure SP secret, GWS SA key, target passwords) | Critical | Fernet-encrypted with tenant key — never returned in API responses |
| Anthropic API key (BYOK) | Critical | Fernet-encrypted with master key |
How It Works
How the key hierarchy works
Master key
- Stored as the
MASTER_ENCRYPTION_KEYenv var in the production environment. - Rotated annually on the major-release schedule.
- Never logged. Never returned from any API. Never written to disk outside the environment secret store.
Tenant Fernet keys
- Generated on first use per tenant.
- Stored in the
tenants.encryption_keycolumn — encrypted with the master key before DB persist. - Used to encrypt sensitive fields on every scan row before insert.
- Decrypted in-process per-request; plaintext never leaves the worker's memory.
Per-field encryption
- Implementation in
app/encryption/fields.py. - Every sensitive finding column goes through
encrypt_field(fernet, plaintext)on insertdecrypt_field(fernet, ciphertext)on read. - The Fernet format (AES-128-CBCHMAC-SHA256 in one token) protects against both tampering and passive snooping.
BYOK — bring your own key
Enterprise customers can supply their own KMS root:
- **AWS KMS*— ARN-based reference to a customer CMK.
- **Azure Key Vault*— vault URIaccess policy or RBAC role.
- **GCP Cloud KMS*— resource pathSA binding.
With BYOK, the tenant's Fernet key is wrapped by your KMS, not Pentestas's master. Revoking your KMS grant immediately denies Pentestas's infrastructure access to your findings. Pentestas staff with DB access see only ciphertext.
Key rotation
When a tenant key rotates:
- New Fernet key generated (or minted via KMS for BYOK).
- Background task re-encrypts every row for that tenant.
- Old key retained for 7 days (defence against rotation mistakes).
- After 7 days, old key is zeroised.
Rotation can be triggered on-demand by an admin or on a schedule (Enterprise).
In Detail
Cross-tenant isolation
Beyond encryption, tenant isolation is enforced at three layers:
Application layer
Every authenticated request sets tenant_id context from the JWT / API key. Every DB query filters WHERE tenant_id = :tid. No authenticated request ever sees another tenant's rows.
DB layer — PostgreSQL Row-Level Security
Every tenant-scoped table has RLS enabled + forced:
ALTER TABLE scans ENABLE ROW LEVEL SECURITY;
ALTER TABLE scans FORCE ROW LEVEL SECURITY;
CREATE POLICY tenant_isolation ON scans
FOR ALL
USING (tenant_id = current_tenant_id())
WITH CHECK (tenant_id = current_tenant_id());The application's DB user is subject to RLS. Even if the application has a SQL-injection bug, queries against the pentestas_app user see zero rows when the tenant context isn't set. Forced RLS means the policy applies to the table owner too, not just regular users — so a SUPERUSER bug wouldn't let you bypass it.
Backup layer
DB backups are per-tenant split — a backup of tenant A cannot be restored in a location with tenant B's encryption key, because the key material doesn't export cleanly across infrastructures. Full cross-region restore requires explicit BYOK key-wrapping re-negotiation.
In Detail
In transit
- **Public APIweb UI*— TLS 1.3 (TLS 1.2 accepted for legacy clients, disabled for Enterprise tenants on request). HSTS preload. OCSP stapling.
- **Internal services (web ↔ DB, web ↔ Redis, worker ↔ anthropic)*— internal Docker network, not exposed externally. Anthropic traffic egresses on TLS 1.3.
- **Agent ↔ platform*— WebSocket over TLS 1.2+. Strict cert pinning to
*.pentestas.com— agents refuse connections that don't match.
In Detail
Credential handling
Target credentials (paths to the system under test)
- Stored in
scan.configJSONB temporarily. - Passed to the Celery worker as part of the task message.
- **Not persisted to the DB after the worker starts.*The
configcolumn is rewritten post-scan to removetarget_username,target_password,cookies,custom_headers, andoauth_refreshfields. - Rescans must re-supply credentials (via
RescanRequestbody) because they're genuinely not saved.
Azure / GWS / cloud credentials
- Stored encrypted per-tenant in
tenants.azure_credentials_encsimilar columns. - Decrypted in-process per scan.
- Never returned in API responses beyond "configured: yes / no"credential type.
Anthropic API keys (BYOK)
- Stored encrypted with the master key (not the tenant key) in
tenants.anthropic_api_key_enc. - Decrypted in-worker only during AI analysis.
- Never logged, never returned.
In Detail
Data retention
| Plan | Scan + finding retention | Backup retention |
|---|---|---|
| Free | 365 days | 30 days |
| Pro | 3 years | 90 days |
| Enterprise | Unlimited (customer-configurable) | 7 years (customer-configurable) |
Retention boundaries auto-purge expired scans. Purges cascade: delete scan → delete findings, reports, attack chains, agent dispatch records.
For regulated entities with specific retention obligations (PCI, HIPAA's 6-year recommendation, SEC 17a-4 for financial records, etc.), Enterprise retention is configurable per data class.
Audit Trail
Audit logging
Every security-relevant action writes an audit row:
- Loginfailed-login attempts (with IPUA).
- Role change / user invitation / user removal.
- API-key create / revoke.
- Scan create / cancel / delete.
- Agent create / disable / delete.
- Settings changes (including credential updates).
- CIS benchmark run, Azure scan dispatch, scheduled-scan modification.
Retention: 365 days on Pro, unlimited on Enterprise. Exportable via API or CSV. Ingest into your own SIEM on every scan completion via webhook.
Compliance
Infrastructure compliance
- **SOC 2 Type II*— ProEnterprise. Report available under NDA.
- **ISO 27001*— certified; certificate on request.
- **GDPR*— data-processor on your behalf; DPA template available.
- **CCPA*— covered under the DPA.
- **HIPAA*— BAA available on BusinessEnterprise.
- **PCI DSS*— Level 4 merchant programme; not a Level 1 service provider but compatible with customer CDE programmes.
- **FedRAMP / HIPAA High / DoD IL5*— not available; custom deployment on-prem or air-gapped is the supported path for those regimes.
In Detail
Responsible disclosure
Security issues in Pentestas itself: security@pentestas.com. PGP key at https://pentestas.com/.well-known/pgp-key.txt. We respond within 24 hours. Accepted reports are credited in our security hall of fame.
In Detail
Incident response (ours)
If Pentestas suspects a tenant-affecting breach:
- Triage within 1 hour of detection.
- Notification to affected tenant admins within 4 hours if confirmed.
- Public disclosure within 7 days (with remediation status) unless law enforcement requests delay.
- Full post-mortem published within 30 days.
Tenant-admin email contact is enforced during onboarding. If you haven't verified a security contact, your first invoice will remind you to.
In Detail
The tl;dr for procurement
- Tenant isolation: applicationDB (RLS)backup. Three-layer.
- Field-level encryption with per-tenant Fernet keys.
- BYOK supported on Enterprise. Customer KMS revocation = immediate denial.
- TLS 1.3 for all external; mutual auth for agent connections.
- Target credentials never persisted post-scan start.
- SOC 2 Type II, ISO 27001, BAA-compatible.
This is the level of detail your procurement team needs. The long-form in Encryption docs has the full specifics.
Evaluate Pentestas against your procurement checklist
Request SOC 2 report under NDA via hello@pentestas.com.
Start your AI pentestMore Reading
Further reading

Alexander Sverdlov
Founder of Pentestas. Author of 2 information security books, cybersecurity speaker at the largest cybersecurity conferences in Asia and a United Nations conference panelist. Former Microsoft security consulting team member, external cybersecurity consultant at the Emirates Nuclear Energy Corporation.