Skip to main content

Hardening guide

Operator

Ticketra ships with strong security defaults. This guide summarizes the built-in protections and gives you a checklist to follow before exposing a deployment.

Built-in protections

API layer

  • CORS restricted to an explicit ALLOWED_ORIGINS allowlist (no open wildcard).
  • Helmet with an explicit Content-Security-Policy, HSTS (1 year), and cross-origin isolation headers.
  • CSRF protection via a double-submit cookie, compared in constant time.
  • Global rate limiting per IP (health checks and SSE exempt).
  • Generic 5xx errors — server errors never leak internal details; client (4xx) errors return actionable messages.
  • Parameterized SQL everywhere — no ORM, no string-built queries with user input.

Authentication

  • JWT sessions pinned to the HS256 algorithm (no algorithm-confusion).
  • Account lockout with tiered backoff and per-account/per-IP login rate limits.
  • Forced password change for the seed admin on first login.
  • Immediate session revocation — disabling a user or revoking sessions drops live SSE streams.
  • Identical error messages for unknown user vs. wrong password (no message-based enumeration).

Real-time (SSE)

  • Authenticated by the same httpOnly cookie as REST (no token in the URL).
  • Per-user and global connection caps; 8-hour session TTL; tenant-isolated broadcasts.
  • Events carry only IDs — clients refetch over REST with full RBAC.

Data & secrets

  • CTI API keys encrypted at rest (AES-256-GCM, scrypt-derived key).
  • Secrets read from Docker secrets, never hardcoded.
  • Attachment/avatar/report downloads defended against path traversal.

Container & network

  • no-new-privileges, cap_drop: ALL, and read-only root filesystems with tmpfs for writable paths.
  • Network segmentation: a frontend-net and an internal-only backend-net (databases are not reachable from outside).

NGINX

  • server_tokens off, a restrictive Permissions-Policy, Referrer-Policy, and a strong SPA Content-Security-Policy.

Production checklist

Use this before going live:

  • Strong, unique secrets generated for jwt_secret (≥32 chars), db_password, admin_password (≥12 chars), and integration_encryption_key.
  • secrets/ and .env are never committed.
  • Changed the seed admin password on first login.
  • ALLOWED_ORIGINS set to your real origin(s) only.
  • Valid TLS certificate in place (internal CA for air-gap), not the self-signed default.
  • trust proxy depth matches your actual proxy chain — an incorrect value lets clients spoof X-Forwarded-For and weaken per-IP rate limiting and audit IPs.
  • Dependencies patched — run npm audit in CI and keep them current.
  • If LDAP is enabled, keep the connect timeout low to reduce login-timing differences (a username-enumeration consideration), and rely on rate limiting + lockout.
  • Backups scheduled, monitored, and test-restored; archives stored off-host on encrypted media.
  • Audit log retention configured per your policy.

Reporting a vulnerability

Found a security issue? Please report it responsibly via the contact published at ticketra.net rather than opening a public issue. A coordinated-disclosure window lets us protect deployments before details are public.