Security

Security first by design

Every layer of this application is built with security as a priority. Your API keys are the most critical asset, and they are never exposed to the browser.

Try the App Deployment Guide

API Key Protection

Server-side keys are never exposed to the browser. In default mode, keys are loaded from environment variables and injected server-side only.

SSRF Protection

Provider URLs are validated via DNS resolution and IP address checks before any request is made. Internal addresses are blocked.

Helmet Headers

Security headers applied automatically: X-Frame-Options, CSP, HSTS, Referrer-Policy, and more.

Rate Limiting

Request rate limiting protects against abuse. Configurable per-route via express-rate-limit.

How API keys are protected

The most important security property of this application is that API keys are never sent to or stored in the browser.

In the default configuration mode (ALLOW_USER_PROVIDERS=0):

  1. API keys are loaded from environment variables at server startup
  2. When a user sends a message, the server appends the key server-side
  3. The browser only communicates with your proxy server
  4. No key ever appears in browser DevTools, network requests, or localStorage

In per-user mode (ALLOW_USER_PROVIDERS=1), each user enters their own key in the browser. These keys are stored in localStorage and only sent to the provider endpoint the user configures. The proxy server never sees or stores user keys.

Server-side protections

SSRF Defense

Before proxying any request, the provider URL is resolved via DNS and the resulting IP is checked against private/reserved ranges. This prevents requests to internal services (metadata endpoints, internal APIs, etc.).

Helmet Headers

The helmet package configures 14+ security headers including X-Content-Type-Options, X-Download-Options, X-Permitted-Cross-Domain-Policies, and Content-Security-Policy.

Rate Limiting

Two rate limiters are applied: one for the chat endpoint (configurable via CHAT_RATE_LIMIT) and one for API keys listing. Prevents abuse and excessive costs.

CORS Configuration

CORS is configured to allow only the same origin by default. Custom origins can be set via CORS_ORIGIN.

No Sensitive Logging

Request logging intentionally excludes API keys and sensitive headers. The LOG_LEVEL environment variable controls verbosity.

Timeout Controls

Proxy requests have configurable timeouts via PROXY_TIMEOUT_MS to prevent hung connections and resource exhaustion.

Browser-side considerations

The frontend is a single-page application with no server-side rendering of content. This means:

Securing your deployment

If you plan to deploy this application publicly, follow these recommendations:

  1. Use HTTPS

    Always serve the application over HTTPS. API keys and conversations are transmitted between the browser and your server.

  2. Set strong environment variables

    Use strong, unique API keys. Set NODE_ENV=production and configure appropriate rate limits.

  3. Add authentication

    Place the application behind a reverse proxy with authentication (e.g., nginx with basic auth, Cloudflare Access, or a dedicated auth middleware).

  4. Keep dependencies updated

    Run npm audit regularly and update dependencies to patch security vulnerabilities.

⚠️
Default mode has no user authentication. Anyone who can reach your server can use the chat. If deploying publicly, add authentication at the infrastructure level (reverse proxy, cloud access control, etc.).