Problem
src/web/write-routes.ts exports a PROTECTED_KEYS set that gates which keys may appear in YAML import/export payloads:
// write-routes.ts ~line 141
/**
* Hand-maintained: keep in lock-step with the `WEBUI_*` and bootstrap env
* vars consumed in src/index.ts and src/web/index.ts. Adding a new env var
* without updating this list will silently let admins overwrite it via YAML.
*/
export const PROTECTED_KEYS: ReadonlySet<string> = new Set([
"DISCORD_TOKEN",
"CLIENT_ID",
"GUILD_ID",
"MONGODB_URI",
"NODE_ENV",
"DEBUG",
"WEBUI_ENABLED",
"WEBUI_BASE_URL",
"WEBUI_SESSION_SECRET",
"WEBUI_SESSION_TTL_MINUTES",
"WEBUI_INACTIVITY_TIMEOUT_MINUTES",
]);
The comment explicitly warns this is hand-maintained. There is no compile-time check, no test, and no lint rule that enforces it stays in sync with:
- The bootstrap vars listed in
src/web/read-only-routes.ts (BOOTSTRAP_VARS)
- The critical settings in
src/services/config-service.ts (criticalSettings)
- Any new
WEBUI_* env var added in the future
A developer who adds a new sensitive env var (e.g. WEBUI_SMTP_PASSWORD, WEBUI_OAUTH_SECRET) and forgets to update PROTECTED_KEYS will expose it to YAML import — a potential privilege-escalation path.
Suggested fix
Derive PROTECTED_KEYS from the same BOOTSTRAP_VARS array that read-only-routes.ts already maintains, or extract the bootstrap vars into a shared constant module and import it in both places. A simple approach:
// src/web/protected-keys.ts (new shared module)
import { BOOTSTRAP_VARS } from "./read-only-routes.js";
export const PROTECTED_KEYS: ReadonlySet<string> = new Set(
BOOTSTRAP_VARS.map((v) => v.key),
);
Then import PROTECTED_KEYS from this module in write-routes.ts and remove the hand-maintained copy.
Add a unit test that asserts PROTECTED_KEYS contains at minimum all keys in BOOTSTRAP_VARS.
Affected files
src/web/write-routes.ts lines 141–153
src/web/read-only-routes.ts lines 66–90 (BOOTSTRAP_VARS)
src/services/config-service.ts lines 452–458 (criticalSettings)
Problem
src/web/write-routes.tsexports aPROTECTED_KEYSset that gates which keys may appear in YAML import/export payloads:The comment explicitly warns this is hand-maintained. There is no compile-time check, no test, and no lint rule that enforces it stays in sync with:
src/web/read-only-routes.ts(BOOTSTRAP_VARS)src/services/config-service.ts(criticalSettings)WEBUI_*env var added in the futureA developer who adds a new sensitive env var (e.g.
WEBUI_SMTP_PASSWORD,WEBUI_OAUTH_SECRET) and forgets to updatePROTECTED_KEYSwill expose it to YAML import — a potential privilege-escalation path.Suggested fix
Derive
PROTECTED_KEYSfrom the sameBOOTSTRAP_VARSarray thatread-only-routes.tsalready maintains, or extract the bootstrap vars into a shared constant module and import it in both places. A simple approach:Then import
PROTECTED_KEYSfrom this module inwrite-routes.tsand remove the hand-maintained copy.Add a unit test that asserts
PROTECTED_KEYScontains at minimum all keys inBOOTSTRAP_VARS.Affected files
src/web/write-routes.tslines 141–153src/web/read-only-routes.tslines 66–90 (BOOTSTRAP_VARS)src/services/config-service.tslines 452–458 (criticalSettings)