From 898c31ac1b139868fd0d86c3cc9402e488f997cd Mon Sep 17 00:00:00 2001 From: Zero Liu Date: Wed, 20 May 2026 23:28:13 -0700 Subject: [PATCH] fix(agent-mode): reject invalid env variable names before commit (#2502) `rowsToRecord` was persisting every non-empty trimmed key, so names failing `ENV_VAR_NAME_RE` (e.g. `BAD KEY`, `FOO=BAR`) flowed through `onChange` into settings and were applied verbatim by backend spawn paths, which read `envOverrides` directly without re-sanitizing. Filter invalid rows at the commit boundary so the persisted record and subprocess env only contain valid POSIX identifiers. Co-authored-by: Claude Opus 4.7 (1M context) --- src/agentMode/backends/shared/EnvOverridesSetting.tsx | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/agentMode/backends/shared/EnvOverridesSetting.tsx b/src/agentMode/backends/shared/EnvOverridesSetting.tsx index 94022460..2ec2b3cf 100644 --- a/src/agentMode/backends/shared/EnvOverridesSetting.tsx +++ b/src/agentMode/backends/shared/EnvOverridesSetting.tsx @@ -43,6 +43,10 @@ function rowsToRecord(rows: Row[]): Record | undefined { for (const row of rows) { const name = row.name.trim(); if (!name) continue; + // Skip names that fail validation so malformed keys never reach + // backend spawn paths, which read `envOverrides` from settings + // directly without re-sanitizing. + if (!ENV_VAR_NAME_RE.test(name)) continue; out[name] = row.value; } return Object.keys(out).length > 0 ? out : undefined; @@ -60,9 +64,10 @@ const COMMIT_DEBOUNCE_MS = 400; * the last edit always lands. The parent's `value` is consulted only at * mount — external reloads while the editor is open are uncommon. * - * Validation is permissive: invalid names surface an inline warning but - * don't block typing. `sanitizeEnvOverrides` drops anything malformed at - * save time, so the persisted shape is always safe. + * Validation is permissive in the input: invalid names surface an inline + * warning but don't block typing. `rowsToRecord` then drops malformed + * rows before commit, so the persisted record (and the env passed to + * backend subprocesses) only ever contains valid POSIX identifiers. */ export const EnvOverridesSetting: React.FC = ({ value,