Security & Compliance
Security first. By default.
Every default in squibble/email assumes the agent's token is already breached. This page documents how the system is built to keep that assumption survivable.
01 Threat Model
An autonomous agent is, by construction, a programmable adversary that already holds your email credentials. Squibble/email is designed around one assumption: the token will leak. Every other defense is in service of making that single failure mode non-catastrophic.
We do not protect against the agent itself acting with full intent. We protect against the blast radius when the agent is compromised, prompt-injected, or its token is exfiltrated through any channel — log files, error messages, an unrelated dependency.
- In scope: token theft, credential reuse, sender spoofing, recipient leakage through logs, replay attacks, suppression-list bypass, send-quota exhaustion.
- Out of scope: recipient-side phishing detection, content classification, recipient mailbox security, DMARC alignment for domains we do not control.
02 Token & Authentication Model
All API access is authenticated via Bearer JWTs that conform to RFC 7519. Each token encodes:
- Mailbox binding — exactly one mailbox per token. The token cannot be redirected to read or send from a different mailbox.
- Scoped actions —
messages:send,messages:index,attachments:show. A send-only token cannot read inbox; a read-only token cannot send. - JTI (JWT ID) — a unique identifier per token. Operators revoke a single token by its JTI in one CLI call; no key rotation, no other tokens affected.
- Issuer + audience — every token is signed by Squibble's issuing key and validated against the API audience claim on every request.
Calling an endpoint outside a token's scope returns
403 with an
RFC 9457 Problem JSON body.
No silent drops, no partial executions.
One token. One mailbox. One verb list. Compromise revokes in a single call.
03 Sender Binding (Anti-Spoofing)
Even if a token is exfiltrated, it cannot be used to spoof an arbitrary
sender. On every POST /api/v1/messages/send:
- From is rewritten to the mailbox encoded in the token's claim.
- Reply-To defaults to the mailbox unless explicitly overridden, and overrides are bounded by domain allowlist.
- Envelope sender (MAIL FROM) is set to a VERP-encoded bounce address per RFC 3464 for authenticated bounce attribution.
A leaked token cannot send mail
as anyone but the bound mailbox — the API has no surface for
raw From: override.
04 Transport Security
Two transport boundaries are enforced fail-closed:
- Client → API (HTTPS). TLS 1.2+ enforced at the edge (Traefik), HSTS preloaded, Let's Encrypt R12 certificates with automated renewal. Plaintext HTTP redirects to HTTPS; there is no plaintext API surface.
- API → upstream SMTP (STARTTLS). Per RFC 3207, a failed STARTTLS upgrade aborts the SMTP session before AUTH. Plaintext credential exposure is structurally impossible — there is no fallback path that authenticates over plaintext.
The decision is binary at the edge: encrypted or no auth attempt. We do not surface a flag to relax this; relaxing it requires a code change.
05 Data at Rest
SMTP credentials for each onboarded mailbox are stored encrypted in Postgres using Fernet (AES-128-CBC + HMAC-SHA256, authenticated symmetric encryption). The encryption key is held in the API runtime environment, never committed to source, and decrypted credentials live in process memory only for the duration of a single dispatch.
Database backups are encrypted at the volume level and stored in the same Switzerland-resident infrastructure as the live database (see Jurisdiction). No customer SMTP credential leaves the EU/CH boundary at any point in its lifecycle.
06 PII Handling & Logging
Operational logs are redacted at write time, in line with GDPR Article 5(1)(c) data minimisation:
- Recipient addresses are scrubbed from
error_logrecords before persistence. - Message bodies are never logged in their entirety; only structural metadata (size, content-type, content-disposition) reaches the log stream.
- Tokens are never logged. Authorization headers are stripped at the access-log layer.
- Idempotency keys are stored as opaque strings and hashed before reaching durable storage.
Engagement events (opens, clicks) record the message UUID, event type, and timestamp — never recipient email or IP beyond what is required to fulfill the redirect.
07 Idempotency
Following the same pattern Stripe established for payment APIs, the
Idempotency-Key header makes
/messages/send safe to retry. The
same key + same payload returns the original response for 24 hours
without double-sending. Same key + different payload returns
409 Conflict — replay detection, not
silent overwrite.
This protects against partial-failure retry storms during agent recovery loops, where a network partition can otherwise cause the same email to be sent dozens of times.
08 Suppression & Bounce Handling
Bounces are classified using RFC 3463 enhanced status codes. Permanent failures (5.x.x) are added to the suppression list immediately; transient failures (4.x.x) remain retryable. Unsubscribes via RFC 8058 one-click are honoured at the same priority. Suppression is per mailbox, not global — each mailbox owns its own list.
Sending to a suppressed address returns 422
with the suppressed recipients enumerated in the response body. We do
not silently drop suppressed recipients from a multi-recipient send;
the entire request is rejected so the caller cannot mistake a partial
success for a full one.
09 Jurisdiction & Compliance
Squibble GmbH is a Swiss company (Kemptthal, Zürich) and the squibble/email infrastructure is hosted in Switzerland. All customer data — mailbox credentials, message metadata, suppression records, idempotency cache — resides under Swiss jurisdiction and is governed by the Swiss Federal Act on Data Protection (revFADP, in force since 1 September 2023).
For customers in the EU, Switzerland is recognised by the European Commission as providing an adequate level of data protection under GDPR Article 45. Personal data flows from EU controllers to Squibble do not require additional safeguards (SCCs, BCRs).
- Data residency: Switzerland (CH).
- Hosting jurisdiction: EU/EFTA only. No US-based subprocessors hold customer data at rest.
- Lawful basis: contract (GDPR Art. 6(1)(b)) for customer data; legitimate interest for operational logs.
- DPA available: we sign a standard Data Processing Agreement on request — contact below.
10 Vulnerability Disclosure
We accept and welcome security reports from the community. If you
believe you have found a vulnerability in
squibble/email,
please report it privately rather than disclose publicly:
- Email: security@squibble.ch
- Acknowledgement window: within two business days.
- Triage & remediation: we aim to validate within five business days and ship a fix within thirty days for non-critical findings; sooner for confirmed critical issues.
- Safe harbour: good-faith research that respects user privacy and avoids destructive testing will not be pursued legally. Do not access data that is not your own; do not run automated scanners against the production API without prior coordination.
For DPA requests, GDPR Article 15/17 enquiries, or compliance questions: hello@squibble.ch.
Want early access?
Join the waitlist and we'll provision your mailbox and first JWT. Most teams ship their first email within a business day of onboarding.