Trust

Security at Obelisk

Security you can verify, not just believe. This page describes how Obelisk protects accounts and data, and how to report a vulnerability.

Last updated 2026-07-29

Security posture

Obelisk is a security product, and we hold ourselves to the bar we sell. Our own live Obelisk Rating is published to the founder console; our public website passes a full external TLS-and-headers scan at A+.

This page is the implementation detail. For the plain-language case — why you can trust Obelisk, end to end — see the full trust case →.

Authentication

  • Passkey-first / WebAuthn. Credentials are public-key based and hardware-bound; the private key is non-exportable and never transmitted. There is no password to phish, reuse, or leak.
  • Discoverable (usernameless) sign-in — one tap, no username to type, phishing-resistant by origin binding.
  • Assurance-bound sessions. Every session carries a signed assurance caveat. A passkey (FIDO2) session is operator-proof: we provably cannot produce that assertion. A code-only (TOTP) session is limited: it can read your account but cannot add or remove a passkey, change recovery or two-factor, or rename you — those always require your passkey. The assurance tier is enforced at every protected endpoint.
  • Optional TOTP second factor with a safe pending→confirm enrolment — a half-finished setup can never lock you out.
  • Recovery codes for last-resort access, stored only as SHA-256 hashes. Using one rotates the rest.
  • Federation — OIDC + SAML. Obelisk is both a full OpenID Connect provider and a SAML 2.0 IdP, issuing RSA-SHA256-signed, cert-pinned SAML assertions. Federate Cloudflare, 1Password, and Microsoft Entra over OIDC, and GitHub, Google Workspace, AWS, Slack, Atlassian and more over the SAML 2.0 IdP — every platform enforcing passkey-first sign-in through one audited front door.
  • Sender-bound tokens — DPoP (RFC 9449). Access tokens can be bound to a client-held P-256 key: the token endpoint accepts a DPoP proof, stamps the key's thumbprint into the token (cnf.jkt), and every protected call must present both the token and a fresh proof signed on-device. A stolen token without the private key is inert — bearer-token replay, the dominant agent-workload threat, is closed. Opt-in per request; the plain bearer flow is untouched.

Data protection

  • Encryption at rest. The identity database is encrypted with AES-256-GCM; secret material is never logged, rendered, or returned by an API.
  • Least disclosure. Relying parties hold zero Obelisk secrets; sessions are verified server-to-server and the relying party receives only a boolean and an identity.
  • Tenant isolation. A shared, encrypted identity plane with proven per-tenant isolation — no two tenants share a return origin, and no artifact carries secret material.

Tamper-evident audit

Every sensitive action — sign-in, token issuance, grant, console access, identity mutation — chains a signed receipt. The chain is independently verifiable: observe nothing without leaving a trace, and the record cannot be quietly rewritten.

Verify it yourself. Every session minted for your account — and every passkey added or removed — is recorded in a tamper-evident, hash-chained log you can read at /account/issuance. Each entry names the credential that authorized it, so you can confirm every sign-in was yours. We turn "trust us, we don't impersonate you" into "verify we didn't."

What we can — and can't — do

We cannot sign in as you. Your passkey's private key never leaves your device; we store only the public key, so no key Obelisk holds can produce a passkey assertion or authenticate as a passkey user. Security-sensitive account changes always require that passkey.

The honest caveat. If you enable a TOTP authenticator, its seed is encrypted at rest under a key our service holds — so in principle an operator with server access could read it. That is exactly why a code-only sign-in is limited to a read-only session, and why we are moving these seeds to per-user sealed storage. For the strongest guarantee, use a passkey, which we provably cannot use on your behalf.

Cryptography & quantum readiness

We use vetted, node-native primitives only — no custom cryptography. We will not ship primitives we cannot stand behind. The full inventory:

  • OIDC tokens — signed ES256 (ECDSA P-256) with JWKS key rotation.
  • SessionsHMAC-SHA256 macaroons with caveat attenuation, so every grant is minimally scoped.
  • Receipts — every sensitive action leaves an Ed25519-signed, hash-chained receipt anchored to a Merkle root.
  • Roster non-membership — proven with sparse Merkle inclusion paths.
  • Disaster-recovery secrets — time-locked with a Wesolowski VDF — they cannot be unlocked before a cryptographic delay elapses.
  • Refresh tokens — rotating, so a stolen token is detectable on next use.
  • Post-quantum — an ML-DSA-65 hybrid signature slot is reserved in every receipt chain, ready to dual-sign the moment a stable standard library lands.
  • SAML federation — assertions signed RSA-SHA256 with a pinned X.509 certificate.

Resilience & availability

A dual-store resilient backend (encrypted primary + immutable break-glass fallback) and an encrypted offline backup mean a corrupted database, a failed migration, or a misconfiguration cannot lock an owner out of their own keys.

Disaster recovery — four independent layers:

  • Daily off-box encrypted backups to Cloudflare R2. critical state (identity DB, receipts, issuance log, client and founder records) is bundled, passphrase-encrypted (PBKDF2 + AES-256-GCM) with an integrity-checked manifest, and shipped off the box. Restore verifies every file's hash and refuses a tampered or corrupt backup — it fails closed.
  • Self-healing health watchdog. a timer probes /healthz every minute and auto-restarts a wedged or crashed process, so a hung instance recovers without a human in the loop.
  • Host-native safeguards. automated whole-box snapshots plus delete- and rebuild-protection backstop the server against an accidental wipe, with an instant address cutover so a rebuilt box takes over without waiting on DNS.
  • External monitoring. an independent uptime probe watches /healthz from outside, so a total outage is caught even if the box can't report on itself.

Lose the entire server and a clean instance restores from the off-box backup with a recovery-time objective of ~15 minutes and at most a day of data at risk. Recovery targets and the honest availability caveat live on the availability & resilience page →

Vulnerability disclosure

Found a vulnerability? We want to hear from you.

Email security@obeliskgate.com with steps to reproduce. Please give us a reasonable time to remediate before public disclosure.

Safe harbor. We will not pursue legal action against good-faith security research that respects this policy: avoids privacy violations, data destruction, and service degradation; tests only accounts you own or have explicit permission to test; and does not access, modify, or exfiltrate other users' data. In scope: obeliskgate.com and the Obelisk identity service. Out of scope: denial-of-service, social engineering, physical attacks, and third-party services we don't operate. A coordinated machine-readable policy is published at /.well-known/security.txt.

The Obelisk Rating

Obelisk continuously scores its own posture across identity strength, never-lockout resilience, database integrity, OIDC health, receipt-chain health, threat coverage, and more — each with a confidence weight. Organizations can run the same engine against their own website. See About.