Skip to content

Security & Encryption

CompassDocs ships with layered protections out of the box. This page explains what the app handles for you, the one key you should look after, and the parts that live at the deployment layer.

  • Passwords are hashed with scrypt (memory-hard) and a per-user random salt — never stored or logged in plain text.
  • Credentials are encrypted at rest (AES-256-GCM): the SMTP password, Anthropic API key, SSO client secret, off-site backup credentials, and any custom TLS private key are sealed with a master key that never touches the database. A stolen database dump yields ciphertext, not your secrets.
  • Session tokens are stored hashed (SHA-256). The raw token exists only in the user’s cookie, so a database leak can’t be replayed as a login. Cookies are httpOnly, SameSite=Lax, and Secure on HTTPS installs, with a sliding idle timeout.
  • API and connector tokens are stored hashed and shown exactly once.
  • Backups are encrypted before they reach disk or an off-site bucket — see Backups & restore.
  • Login throttling: five failed attempts for the same account and address within 15 minutes locks that pair out for 15 minutes (wrong two-factor codes count too); sprays from a single address are locked after 30 failures. Every lockout lands in the audit log as auth.lockout.
  • Security headers on every response: Strict-Transport-Security, X-Content-Type-Options: nosniff, Referrer-Policy, a restrictive Permissions-Policy, and an anti-clickjacking Content-Security-Policy. The Outlook add-in task pane keeps a carve-out so Outlook can embed it — no configuration needed.
  • CSRF protection: cookie-authenticated API requests are rejected when a browser presents a cross-origin Origin (layered on top of the SameSite=Lax cookies), so a malicious page can’t drive the app with a signed-in user’s session.
  • SSRF protection: the server only fetches admin-supplied URLs (quick-link icons, workspace logos, outgoing webhooks) after checking the target — cloud metadata endpoints (169.254.169.254), loopback, and link-local addresses are refused, and every redirect hop is re-validated. Intranet (RFC1918) hosts stay reachable so webhooks and links to internal tools work; set COMPASSDOCS_FETCH_BLOCK_PRIVATE=1 to refuse those too on a hardened deployment.
  • Outbound proxy support (0.74.1): on networks that require egress through a proxy, set HTTPS_PROXY (and optionally NO_PROXY) on the container — status polls, outgoing webhooks, AI/embeddings calls, and every other server-side fetch route through it. If the proxy re-signs TLS with a corporate CA, also mount the CA and set NODE_EXTRA_CA_CERTS=/path/to/ca.pem. Settings → System → Diagnostics has an Outbound HTTPS check that verifies egress (direct or proxied) and names the blocker when it fails.
  • Dependency & image scanning run in CI (npm audit, Trivy for vulnerabilities/secrets/misconfig, and Dependabot update PRs), so known-bad dependencies are caught before a release ships.
  • The container runs as a non-root user (uid/gid 1001 as of 0.59.0), so a process escape doesn’t land as root. Only the data directories it needs (/uploads, /backups, custom-TLS certs) are writable.
  • Two-factor auth (authenticator apps + recovery codes) is available on every account — turn it on for admins first. Enterprise installs can move sign-in to Microsoft Entra SSO entirely.

Everything encrypted at rest is sealed under one 32-byte master key. It is resolved in this order:

  1. COMPASSDOCS_SECRET_KEY environment variable — 64 hex characters or 44 base64 characters. Recommended for production; generate one with:

    Terminal window
    openssl rand -hex 32
  2. A key file, auto-generated on first boot with 0600 permissions at $COMPASSDOCS_UPLOAD_DIR/.secret.key (inside the uploads volume, so it survives container recreates). Set COMPASSDOCS_KEY_FILE to move it.

Upgrading to 0.41+ migrates existing plaintext credentials and session rows automatically on first boot — nobody is signed out, and nothing needs re-entering.

The app cannot encrypt the disk it runs on. For full encryption at rest of content (documents, attachments, the directory), use the layer below:

  • Encrypted volumes or disks — LUKS on your own hardware, or the encrypted-disk checkbox every major cloud offers. This covers Postgres data, uploads, and local backups wholesale.
  • Managed Postgres (Azure Database, RDS, Fly Postgres, Neon, …) — all encrypt storage at rest by default and handle TLS to the database. For an external database, add ?sslmode=require to DATABASE_URL.
  • HTTPS — use the built-in custom domain & HTTPS stack (Caddy with automatic Let’s Encrypt) or your own reverse proxy. Never serve a workspace over plain HTTP beyond localhost.
  • Host basics — keep the Docker host patched, restrict SSH, and don’t expose Postgres’s port publicly (the compose files don’t).
  1. Set COMPASSDOCS_SECRET_KEY (or copy the auto-generated key file) into your password manager.
  2. Serve over HTTPS with the built-in Caddy stack or your proxy.
  3. Turn on 2FA for every admin account.
  4. Enable scheduled backups with an off-site destination — and test a restore.
  5. Use encrypted disks (or managed Postgres) so document content is covered.
  6. Skim the audit log for auth.lockout and failed sign-ins now and then.