Trust center · Security overview
Every claim, mapped to evidence.
Architecture deep-dive lives at /security; this page is what you skim before scheduling a vendor review call. Each claim links to the code, test, or doc you can verify for yourself.
Authentication & access
- ✓
API keys are scrypt-hashed at rest
The readable key is never written to any storage, anywhere — it's one-way scrambled (scrypt) first. The scrambler's strength settings (hash params N=2^15, r=8, p=1) live alongside the hash so keys can be verified without ever storing the key itself. A database breach surfaces hashes, not credentials.
apps/server/src/lib/api-keys.ts · hashApiKey() / verifyApiKey()
- ✓
MFA: TOTP + recovery codes
Two-factor login uses authenticator-app codes (TOTP). The seed that generates your codes is stored encrypted (AES-256-GCM at-rest encryption of TOTP secrets). Recovery codes are scrypt-hashed — one-way scrambled, mirroring API key handling. Dangerous admin actions demand a fresh MFA check even if you're already signed in (a "step-up" gate on destructive admin paths).
apps/server/src/lib/mfa-totp.ts · apps/server/src/services/mfa.ts
- ✓
OAuth 2.0 (invite-only) with PKCE-S256
Third-party app access (OAuth) requires admin invitation (no self-service client registration). Every connection uses PKCE-S256 — an extra proof that the app finishing a login is the same one that started it. App secrets (client_secret) are sha256-hashed at rest; login codes work exactly once (one-shot authorization codes); and access tokens are opaque random strings (no JWT), so a stolen token carries no readable data.
apps/server/src/services/oauth.ts · apps/server/src/lib/oauth-pkce.ts
- ✓
BYOK Anthropic keys + gui_control_keys + Mac LiveKit secrets: AES-256-GCM at rest
Three kinds of secrets that would be as damaging as passwords if leaked ("plaintext-equivalent" material) live in AES-256-GCM ciphertext under the same host-resident encryption key as MFA TOTP secrets: (1) your own Anthropic API key, if you bring one for the AI agent (BYOK — bring your own key); (2) the per-session keys that authenticate desktop-app control commands (gui_control_keys — HMAC keys); and (3) the LiveKit secrets each Mac in our fleet registers via POST /v1/mac-nodes/register, which the platform uses to create the short-lived video-access tokens (JWTs) the desktop app needs to watch a live session. All three are decrypted in-memory only at execution time, never logged, never echoed in responses. Our logging and error-reporting layers also scrub secrets automatically (Pino-redact + Sentry-scrub) in case one ever ends up inside a message.
apps/server/src/services/byok-anthropic.ts · apps/server/src/lib/byok-anthropic-encryption.ts · apps/server/src/lib/livekit-secret-encryption.ts
Transport & egress
- ✓
TLS 1.3 on every customer-facing path
Cloudflare, our edge network, enforces strict TLS 1.3 encryption all the way to our own servers behind
api.driftstack.dev+app.driftstack.dev(the origins). No unencrypted page (plaintext HTTP) exists on any path — every release is automatically checked for this before it ships; the deploy pipeline's TLS check rejects the release otherwise. - ✓
Customer-configurable egress (per profile)
Each profile can attach its own egress — its own exit to the internet: a SOCKS5 proxy with full UDP/WebRTC/QUIC tunnelling (the video-call and modern-web traffic types many proxies drop), an OpenVPN file (.ovpn), or a WireGuard file (.conf). A session bound to the profile connects to your proxy or VPN ("dials the tunnel") before the browser launches, and address-lookup traffic can't slip out around it (DNS leaks blocked). Without an attached config, session traffic exits via Driftstack's own EU network egress. Driftstack does not log session-traffic payloads (the destination URLs you visit, the page content that comes back); the proxy layer passes traffic through without storing it.
Webhooks & integrations
- ✓
Outbound webhooks are HMAC-SHA256 signed
A webhook is a message we send to your systems when something happens. Every delivery carries
X-Driftstack-Signature— a cryptographic signature (HMAC) over the timestamp + message body. Your code verifies it via one SDK helper; messages older than the allowed timestamp tolerance window are rejected, so an intercepted copy can't be re-sent later (replay attacks).apps/server/src/lib/webhook-signing.ts
- ✓
Inbound webhooks (Stripe, NowPayments) signature-verified before any state mutation
Payment notifications must prove they're genuine before we change anything on your account. Stripe: timestamp + sha256 HMAC. NowPayments: HMAC-SHA512 over the normalised (canonical-keyed) JSON. A shared raw-body parser ensures the exact bytes the signature was computed over are the bytes the verifier sees — nothing can be altered in transit without detection.
apps/server/src/lib/stripe-signing.ts · apps/server/src/lib/nowpayments-signing.ts
Data residency & retention
- ✓
EU control plane
Compute (Hetzner Nuremberg), database (Neon Frankfurt), object storage (Cloudflare R2, EU + US replication). The iPhone Safari session-execution fleet runs on MacStadium hardware (US) under SCCs (the EU's Standard Contractual Clauses for lawful data transfer abroad) + the EU-US Data Privacy Framework — see data residency. Full sub-processor list at /trust/sub-processors.
- ○
Capture retention (roadmap)
Today, screenshots and captures are returned directly inside the API response (inline bytes) and are not kept on our servers afterwards — so there is no retention setting to configure yet. Stored session recordings, with controls over how long they're kept, are on the roadmap — see /docs/recordings.
- ✓
Account deletion: 30-day grace, then hard delete
For 30 days after cancellation your data is only flagged as deleted ("soft-delete") and can be restored if you come back. After that it is permanently erased (hard delete) — profile data, sessions, captures. Per our DPA.
Observability & incident response
- ✓
Public incident history + status page
Customer-impacting outages are posted publicly within the incident-response SLA window. Live status at status.driftstack.dev; historical archive at /trust/incidents.
- ✓
Vulnerability reports: acknowledged in 2 days, assessed in 5 (triage)
We won't take legal action against good-faith research ("safe-harbour"). Reporters agree to keep a finding private for 90 days while we fix it (the coordinated disclosure window), extendable on agreement. Full policy at /trust/compliance.
- ✓
We rehearse failures on purpose (chaos engineering)
Vendor (sub-processor) outages, the database switching to its backup (DB failover), the Redis cache going down, webhook-signature failures — all covered by scripted drills in
scripts/chaos/. Drills run as simulations by default (dry-run); actually breaking things (execute mode) requires explicit operator opt-in.scripts/chaos/
Still need a deeper look?
The architecture deep-dive at /security walks the six-pillar surface in detail. For pen-test evidence or compliance certifications, see /trust/compliance. Anything else, just email.