DOCS · SECURITY

Security & authentication

Cortex can protect its browser interface without requiring terminal-side account setup. The first browser visit creates the instance password; subsequent visits require authentication before Cortex exposes its workspaces, settings or coding-agent APIs.

First-run password

Start Cortex normally and open it in the browser. If the instance has not been configured yet, Cortex shows the setup screen and asks you to create a password. The password is stored as a salted PBKDF2-HMAC-SHA256 verifier rather than plaintext. Successful login creates an HttpOnly, SameSite session cookie.

Session lifecycle

A successful password or Google login creates a random HttpOnly, SameSite Strict session cookie that expires after seven days. Cortex keeps at most eight sessions and evicts the oldest when the cap is reached. Sessions are intentionally memory-only: restarting Cortex revokes all browsers. Changing the password revokes every existing session and rotates the current browser to a fresh credential.

Repeated failed logins are throttled per direct client. The tracker is bounded so hostile source addresses cannot grow it without limit.

TOTP two-factor authentication

TOTP is optional. Enrollment is bound to the current session and expires after ten minutes. A code accepted for login cannot be replayed during the same validity window. Open Settings → Security, create the authenticator secret, add it to your authenticator application, then enter a current six-digit code to verify setup. Once enabled, password login requires both the password and a current TOTP code.

Google sign-in

OAuth authorization uses single-use, ten-minute state entries and PKCE S256, and the callback remains bound to the redirect URI that initiated sign-in. Cortex caps outstanding OAuth states to prevent unbounded memory use.

Google authentication is also optional and self-configured. In Settings → Security, provide your Google OAuth client ID and client secret, then set the single Google email address allowed to access this Cortex instance. Cortex displays the exact authorized redirect URI to add to the Google OAuth client configuration.

Restricting Google login to the configured email is intentional: a valid Google account alone does not grant access to Cortex.

Change password and logout

The Security settings also provide password changes and logout. Changing the password requires the existing authenticated Cortex session; secrets remain server-side.

Backend enforcement

Authentication is not just a browser overlay. Protected workspace, provider/settings and agent endpoints reject unauthenticated requests. This matters because a Cortex process can ultimately edit files and execute commands with the operating-system authority of the account running it.

Remote deployments

Authentication makes remote Cortex substantially safer to operate, but it does not turn a high-authority coding-agent service into a low-risk public website. Use HTTPS when traffic crosses an untrusted network and consider a private network or authenticated reverse proxy as an additional boundary for Internet-facing deployments.

Battle-hardening result

The complete CX00-CX11 campaign classifies all 20 API routes and tests authentication, CSRF, proxy, workspace, secret, subprocess, hostile stream, persistence, overload and release boundaries. See the Battle Tested evidence ledger for commands and retained risks.

HTTP and browser boundary

Cortex limits request headers to 1 MiB, allows five seconds for headers, 30 seconds for request reads and 60 seconds for idle connections. JSON endpoints enforce their route methods, require application/json for bodies and reject unknown fields or trailing documents. API responses are non-cacheable. Agent responses intentionally have no global write deadline because they stream while OpenCode is running; agent concurrency, process ownership and output volume are bounded independently.

CSRF and origin enforcement

Cookie-authenticated mutations require a per-session CSRF token sent in X-Cortex-CSRF and an exact same-origin Origin. Setup and login submissions also require same-origin requests. Missing, duplicated or stale credentials and malformed origins are rejected before the handler runs.

Proxy trust

Forwarding headers are ignored unless Cortex is started with --trust-proxy, and even then only its direct loopback peer is trusted. Use --public-origin https://cortex.example.com to pin external Host and origin checks. Never enable proxy trust if clients can reach the backend port directly.