EODView is a single-user app. It has no user accounts; it protects what matters as follows:
- EODHD API key — stays on the server (
server/data/config.json, mode 0600, orEODHD_API_KEY). It is never sent to the browser, logged, or included in error messages. - Admin routes (
/api/config,/api/tokens, universe jobs/markets) — only loopback callers with a loopbackHostand no proxy headers, orAuthorization: Bearer $EODVIEW_ADMIN_TOKENwhen that is set. - Agent API (
/api/v1,/mcp) — read-only; loopback callers or bearer tokens (stored as SHA-256 hashes, constant-time compare), per-token rate limits and a separate daily EODHD credit budget. - Cross-site requests —
/wsupgrades and state-changing/apirequests from foreign origins are rejected; JSON bodies must beapplication/json. - Screener SQL — every column is whitelisted and every value is a bound parameter.
Everything else (charts, watchlists, alerts, drawings, screener) is open to anyone who can reach the server.
Put an authenticating proxy in front and tell the app it is proxied:
- Use Cloudflare Access (see deploy/README.md), an identity-aware proxy, or equivalent.
- Set
EODVIEW_ADMIN_TOKENandEODVIEW_API_REQUIRE_TOKEN=1. A reverse proxy on the same machine forwards requests from127.0.0.1; without these settings, those requests look local. - Set
EODVIEW_ALLOWED_ORIGINS=https://your-hostif the public origin differs from theHostheader the app sees.
None are committed. Deployment secrets live in Google Secret Manager, and local configuration lives in
deploy/.env.local and server/data/. Both are gitignored.
Please open a private security advisory on GitHub rather than a public issue.