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):
- API keys are loaded from environment variables at server startup
- When a user sends a message, the server appends the key server-side
- The browser only communicates with your proxy server
- 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:
- No server-side templates to inject — all content is rendered client-side
- No client-side storage of API keys in default mode
- Chat history is local-only — stored in IndexedDB on the user's device
- No third-party analytics or tracking scripts
- CSP headers prevent inline script injection
Securing your deployment
If you plan to deploy this application publicly, follow these recommendations:
-
Use HTTPS
Always serve the application over HTTPS. API keys and conversations are transmitted between the browser and your server.
-
Set strong environment variables
Use strong, unique API keys. Set
NODE_ENV=productionand configure appropriate rate limits. -
Add authentication
Place the application behind a reverse proxy with authentication (e.g., nginx with basic auth, Cloudflare Access, or a dedicated auth middleware).
-
Keep dependencies updated
Run
npm auditregularly and update dependencies to patch security vulnerabilities.