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.
What the app does for you
Section titled “What the app does for you”- 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, andSecureon 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 restrictivePermissions-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 theSameSite=Laxcookies), 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; setCOMPASSDOCS_FETCH_BLOCK_PRIVATE=1to 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 optionallyNO_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 setNODE_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.
The master key
Section titled “The master key”Everything encrypted at rest is sealed under one 32-byte master key. It is resolved in this order:
-
COMPASSDOCS_SECRET_KEYenvironment variable — 64 hex characters or 44 base64 characters. Recommended for production; generate one with:Terminal window openssl rand -hex 32 -
A key file, auto-generated on first boot with
0600permissions at$COMPASSDOCS_UPLOAD_DIR/.secret.key(inside the uploads volume, so it survives container recreates). SetCOMPASSDOCS_KEY_FILEto 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.
What belongs to your deployment
Section titled “What belongs to your deployment”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=requiretoDATABASE_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).
Quick checklist
Section titled “Quick checklist”- Set
COMPASSDOCS_SECRET_KEY(or copy the auto-generated key file) into your password manager. - Serve over HTTPS with the built-in Caddy stack or your proxy.
- Turn on 2FA for every admin account.
- Enable scheduled backups with an off-site destination — and test a restore.
- Use encrypted disks (or managed Postgres) so document content is covered.
- Skim the audit log for
auth.lockoutand failed sign-ins now and then.
