The Atlas Lavern's documentation, bound to its code
111 documents
SECURITY.md

Vulnerability reporting (48h ack / 7d updates), explicit scope and trust boundaries, what LOCAL MODE does and doesn't protect, ten implemented defenses (SSRF prevention, SMAC-L1 sanitization, rate limiting…) and the hardening roadmap. You're reporting a vulnerability or assessing the threat model.

Security

Thank you for taking the time to look at Lavern's security.

Reporting a vulnerability

Do not file public GitHub issues for security bugs.

Email hello@lavern.ai with:

  • A description of the issue
  • Steps to reproduce (or a proof-of-concept)
  • The version / commit hash you tested against
  • Whether you believe it is being actively exploited

We will:

  • Acknowledge receipt within 48 hours
  • Provide a status update within 7 days
  • Credit you in the release notes (or remain anonymous on request)
  • Coordinate disclosure timing with you (default 90 days from acknowledgement)

Scope

In scope:

  • The Lavern API server (src/api/)
  • The Clawern daemon (src/claw/)
  • The dashboard (viz/)
  • The Anthropic provider, Mistral provider, local Ollama provider
  • The MCP remote bridge (when enabled)
  • The agent-builder firm-clone flow
  • Auth, billing, and session management

Out of scope:

  • Vulnerabilities in upstream dependencies — please report those to the upstream project (we will track and patch)
  • Issues in deployed instances of Lavern operated by third parties (report to that operator)
  • Social-engineering attacks against Lavern team members
  • Physical attacks on the host running Lavern
  • Findings that require already-compromised credentials, root access, or a malicious browser extension

Deployment shapes

v0.15.0 ships with LAVERN_AUTH_ENABLED=false by default. In that LOCAL MODE, every request is the synthetic local-user, no cookies are set, no passwords are stored, no Stripe webhooks are accepted, and the auth/billing/Google-OAuth/referral routes don't register at all. The threat model collapses to "single user on a machine they own" — most of the trust boundaries below are inert until the flag is flipped.

The multi-user model below applies when LAVERN_AUTH_ENABLED=true (shared / hosted deployments). The auth backend code is preserved on the same branch; flipping the flag and restarting brings it back online with no migration.

Trust boundaries

Lavern protects:

  • The user's authenticated session and password hash
  • Document content uploaded by an authenticated user
  • The session event stream (sessions are only readable by their creator or by anyone with the session ID, which is treated as a capability token — see src/api/server.ts public-paths comment)
  • Billing data (held holds + debits)
  • API keys configured by the operator (Anthropic, Mistral, Stripe, Resend)

Lavern does not protect against:

  • A malicious operator (the Lavern instance owner can read any user's data — Lavern is single-tenant by design)
  • A malicious local model (the Ollama daemon runs as the user and can read any file the user can)
  • Network attackers between the browser and the API when run over HTTP (use a TLS-terminating reverse proxy)
  • Compromised host operating system

What we already do

  • Bearer-token + cookie auth (src/api/middleware/auth.ts)
  • bcrypt password hashes
  • Atomic password-reset tokens (single-use, time-limited)
  • Constant-time login delay for non-existent users (timing-attack mitigation)
  • Generic error messages on auth failure (no account enumeration)
  • Per-route rate limiting + global per-user limiter
  • Server-side WebSocket heartbeat with idle timeout
  • SSRF prevention on the firm-scraper (private IPs blocked, content-type checked, size capped, fetch timeout)
  • Symlink-traversal protection on Clawern watch paths
  • XSS sanitisation on all assembled HTML deliverables (no <script>, no <iframe>, no event handlers)
  • SMAC-L1 input sanitisation on all parsed documents (zero-width Unicode, HTML comments, ANSI escapes stripped)
  • CSRF-state token on the Google OAuth flow
  • Email verification gate on POST mutations for browser users
  • Production startup validation (refuses to start with localhost defaults in NODE_ENV=production)
  • Sentry coverage on silent-failure paths (session archive, webhook delivery, Stripe signature verification)

What we do not yet do (roadmap)

  • DNS-rebinding protection (resolve once, lock the IP for the fetch).
  • PDF/DOCX parsing in a worker-thread sandbox with memory + wall-clock caps
  • Helmet-equivalent default security headers (CSP, HSTS, X-Frame-Options, Referrer-Policy)
  • CSRF tokens on cookie-authed mutations beyond OAuth callbacks
  • Signed npm publishes with provenance attestation