Security and trust
Every statement on this page is labelled with its status and traced to a document in the repository. Where something is not done, it says so.
Zero data retention
What is verified
- 1.1
No deliberate write to disk
No code path in the gateway writes raw input, masked output or the mapping table to disk, a log or a database. The container runs a read-only root filesystem with an in-memory /tmp. Measured: 200 PII-laden requests against the hardened container, all reconstituted, with a zero write-bytes delta on the process; the same check runs in CI on every change.
- 1.2
Deletion at the end of the request
The mapping table is deleted from memory when the stream closes, with a safety-net time-to-live that renews on activity and an absolute cap for long reasoning models.
- 1.3
Buffers under our control are overwritten
Every raw buffer the application holds is overwritten with zeros immediately after the attestation is signed.
- 1.4
A cryptographic receipt on every response
The X-zer0pii-Attestation header is an Ed25519 signature over the hashes of the raw and the masked request, verifiable independently against the published JWKS. It attests to the hashing and to the overwrite of the buffers the application controls.
What it does not promise in the current runtime
- Transient copies made by the Python runtime (the ASGI server, the JSON decoder, the regex engine) are released to the garbage collector but are not physically zeroed at once.
- Operating-system mitigations (memory locking, swap disabled, core dumps disabled, read-only filesystem) reduce this exposure but do not remove it. Exploiting it requires reading the live process memory, which means an attacker who already runs code on the host.
- Closing the gap fully is planned for a future data plane (a Rust core with deterministic zeroization, or a hardware enclave with silicon-level attestation). Until then, any "RAM scrub" wording means the buffers described above and nothing more.
The scope document overrides any marketing wording, including this page.
Source: docs/ZDR-SCOPE.md
Architecture in brief
A gateway that speaks the OpenAI, Anthropic and Gemini request formats sits between your tools and the provider. A deterministic tier catches identifiers with a fixed shape; a semantic tier detects names, organisations and places. Placeholder tags are derived from a keyed hash scoped to the conversation, so a provider's prompt cache keeps working and tags cannot be reversed to values. The browser extension runs the deterministic tier on-device before a prompt leaves the page.
Code is protected from masking by design: variable names, packages and syntax are left alone, and only hardcoded credentials inside code are redacted. That guard prevents false positives; it is not a barrier against a deliberate insider splitting a value across variables.
Source: docs/ZDR-SCOPE.md, docs/dev-tools/README.md
SOC 2
zer0pii is actively pursuing a SOC 2 Type II report with Security and Confidentiality in scope. Scope is decided and the readiness work is under way. No report exists yet, no date is promised here, and zer0pii does not describe itself as SOC 2 compliant before a licensed firm issues one.
Source: docs/compliance/soc2-readiness-plan.md
Data processing agreement
A DPA template written so that every technical statement in it matches the code and the scope document is available for counsel review. Ask for it from the legal page; it is offered after legal review, not before.
Request the DPASource: docs/legal/dpa-template.md
Subprocessors
The register is the repository document; this is its verified section. A row is listed only when the vendor can be pointed to in code or configuration.
| Subprocessor | Purpose | Data it receives | Status |
|---|---|---|---|
| OpenAI | Upstream LLM provider, chosen by the customer per request | Masked text; the customer's provider key in transit | Verified |
| Anthropic | Upstream LLM provider, chosen by the customer per request | Masked text; the customer's provider key in transit | Verified |
| Google (Gemini API) | Upstream LLM provider, chosen by the customer per request | Masked text; the customer's provider key in transit | Verified |
| Any OpenAI-compatible endpoint the customer configures | Upstream LLM provider | Masked text; the customer's provider key in transit | Verified as a mechanism; the vendor is the customer's |
| Amazon Web Services, S3 | Customer-owned SIEM export bucket | Metadata only (event ids, labels, counts, hashed key), never text | Verified, customer-elected |
| The customer's SIEM webhook receiver | Operator-level CEF forwarding | Metadata only | Verified as a mechanism; off unless configured |
| The customer's identity provider | SSO login and SCIM provisioning | Account data (member email, roles) | Verified as a mechanism; the IdP is the customer's |
| SMTP relay | Magic-link and invite email | Account data (recipient address, the link) | Verified as a mechanism; vendor name to be filled by the owner |
| Hosting platform for the gateway and console | Runs the data plane and control plane | Raw text in RAM only; masked text, metadata and account data | Verified as Dokploy on a single VPS; infrastructure provider and region to be confirmed by the owner |
| Stripe | Self-serve checkout and plan webhooks | Account data only (org id, owner email); card data is entered on Stripe pages | Verified as a mechanism; off unless configured |
| Hosted status-page provider | Public status page, polls a public probe | None of the categories above: hostname, status code, latency | Recommended; account probe pending |
Only the LLM providers receive text at all, and what they receive is masked. No subprocessor receives raw text.
Source: docs/compliance/subprocessor-list.md
Transparency report
The quarterly report format is published before the first edition: government and legal requests, disclosed incidents, subprocessor changes, uptime as published by the status page, and the zero-data-retention attestation summary. By decision it carries no error rates and no per-customer data.
Read the template (Repository path): docs/transparency-report-template.md
Detection coverage
What the engine looks for, in plain words. Numbers live in the weekly accuracy report committed to the repository, not on this page, because a fleet-wide figure would be read as a guarantee for your text.
Identifiers with a fixed shape (deterministic tier, checksummed where a checksum exists)
- Email addresses
- Phone numbers, including irregular separators
- National identity numbers: Israeli ID, US SSN, UK NINO, German tax ID, French NIR, Spanish DNI/NIE, Italian codice fiscale, and others
- Payment card numbers, IBANs, SWIFT/BIC, Israeli bank accounts, VAT numbers
- IP addresses
- Cloud and provider credentials (AWS, OpenAI, Anthropic, GitHub, Slack), private keys, passwords inside connection strings, high-entropy secrets
Free-text entities (semantic tier)
- People's names
- Organisations
- Places and addresses
Languages the semantic tier is evaluated on
- Hebrew
- English
- Arabic
- German
- French
- Spanish
Known limits are documented rather than hidden: a value that looks like an ID but fails its checksum is left alone by design; a value that passes two countries' checksums is labelled by the first rule; prose that describes a number format can be masked as if it were a value; some national-ID values fall through to the phone label.
Weekly report location in the repository: docs/accuracy/
Entity catalogSource: docs/ENTITY-CATALOG.md, docs/known-limitations/masking-mislabels.md, docs/accuracy/
Responsible disclosure
Found a vulnerability? Write to the security mailbox. Say what you found and how to reproduce it; do not include real personal data in the report. We acknowledge every report and keep you informed until it is closed.
security@zer0pii.com