Security

How instadoc protects your data and your renders.

Identity & authentication

  • Dashboard auth: Clerk hosted identity (TOTP/MFA supported).
  • API auth: bearer keys of the form ido_live_<24 base62> (≈143 bits of entropy), stored only as an argon2id hash + 8-char prefix. The full key is shown exactly once at creation.
  • Keys can be revoked or rotated instantly from the dashboard.

Rendering sandbox

  • Templates execute inside Jinja2's SandboxedEnvironment — no eval, no dunder access, no filesystem, no subprocess spawning.
  • Every render is XML-autoescaped by default; HTML pipes through a sanitising filter that strips <script>, <style>, <iframe>, etc.
  • 15-second wall-clock timeout on every render; optional process-level isolation with memory ulimits for additional defense-in-depth.
  • Uploaded files are MIME-sniffed and inspected — macro-enabled archives (vbaProject.bin anywhere) are rejected at upload.

Data at rest

  • Postgres encrypted at rest; daily backups (when deployed).
  • Object storage encrypted at rest (DigitalOcean Spaces).
  • API-key hashes use argon2id with OWASP-recommended cost.

Network

  • HTTPS everywhere (HSTS in production).
  • CORS allowlisted to your configured frontend origins.
  • Strict Content-Security-Policy on every backend response.
  • Rate limits: 60 req/min/key and 300 req/min/IP, with X-RateLimit-* headers so clients can back off proactively.

Audit trail

Every privileged action (suspending a user, rotating an API key, deleting a template, role change) writes an entry to the audit log with actor, target, IP, user-agent and timestamp. Admin UI includes a persistent "Admin mode" banner.

Report a vulnerability

Email [email protected] with reproduction steps. We aim to acknowledge within 1 working day and resolve critical issues within 7. Please don't share findings publicly until we've had a chance to patch.