Module-level const assignments (SONARR_API_KEY, RADARR_API_KEY,
SABNZBD_API_KEY, EMBY_URL, EMBY_API_KEY) captured values at startup
and would not pick up rotated credentials without a restart.
Replaced all module-level captures in emby.js, sabnzbd.js, sonarr.js,
radarr.js, and dashboard.js with inline process.env reads at each
call site. A process restart is still needed for dotenv-loaded values
but environment-injected vars (Docker, Kubernetes) are re-read live.
Added server/utils/sanitizeError.js which redacts:
- ?apikey= query parameters (SABnzbd passes key in URL)
- ?token= query parameters
- X-Api-Key / X-MediaBrowser-Token / X-Emby-Authorization header
values if they appear in the error message string
Applied to all catch blocks in emby.js, sabnzbd.js, sonarr.js,
radarr.js, and dashboard.js. Internal error.message still logged
server-side (unredacted) for debugging.
#1 Session cookie: add secure (production-only) and sameSite=strict
to prevent transmission over HTTP and cross-site request abuse.
#2 Remove Emby AccessToken from cookie payload — it was stored in
the browser cookie but is never needed client-side; reduces blast
radius if cookie is ever exposed.
#3 Add requireAuth middleware to all proxy routes (/api/emby,
/api/sabnzbd, /api/sonarr, /api/radarr) — previously unauthenticated,
now require a valid emby_user session cookie.
#4 Remove open CORS wildcard (cors() with no options). The frontend
is served from the same origin so no CORS headers are required.
Also update clearCookie() to include matching cookie options.