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.