fix(codex-config): stop rejecting env values that start with "-"

--env's value is the RHS of one KEY=VALUE argv element, never its own
argv position, so a leading "-" can never be parsed as a flag — unlike
the key, which stays validated as an identifier. assertArg's leading-dash
guard was reused for the value too, refusing ordinary values like "-1".
Split it into assertEnvValue (no leading-dash check) for values only.
This commit is contained in:
2026-09-09 01:22:12 +07:00
parent acff059e92
commit 42db57ee18
2 changed files with 33 additions and 1 deletions
+14
View File
@@ -189,6 +189,20 @@ describe("codex-cli argv construction", () => {
}
});
it("accepts an env value starting with '-' — it's the RHS of one KEY=VALUE argv element, never a flag", async () => {
const restore = stubCodex();
try {
const result = await cli.mcpAdd({
name: "docs",
command: "node",
env: { OFFSET: "-1" },
});
assert.deepEqual(argvOf(result), ["mcp", "add", "docs", "--env", "OFFSET=-1", "--", "node"]);
} finally {
restore();
}
});
it("builds mcp list / remove argvs", async () => {
const restore = stubCodex();
try {
+19 -1
View File
@@ -94,6 +94,24 @@ function assertEnvKey(value, label) {
return value;
}
/**
* An environment variable VALUE. Unlike `assertArg`, a leading "-" is fine:
* the value is the right-hand side of one `KEY=VALUE` argv element (built
* by envFlags below), never its own argv position, so it can never be
* parsed as a flag. Rejecting it anyway (as `assertArg` would) refused
* ordinary values like "-1" or a base64 string that happens to start with
* "-" for no real reason.
*/
function assertEnvValue(value, label) {
if (typeof value !== "string") throw makeError("EBADARG", `${label} is required`);
if (value.length > 512) throw makeError("EBADARG", `${label} is too long`);
// eslint-disable-next-line no-control-regex
if (/[\u0000-\u001f\u007f]/.test(value)) {
throw makeError("EBADARG", `${label} contains control characters`);
}
return value;
}
/** An http(s) URL — `new URL()` both validates and normalizes the parse. */
function assertUrl(value, label) {
assertArg(value, label);
@@ -219,7 +237,7 @@ async function mcpAdd({ name, url, bearerTokenEnvVar, command, args = [], env })
const cmdArgs = args.map((a, i) => assertArg(a, `args[${i}]`));
const envFlags = Object.entries(env || {}).flatMap(([k, v]) => {
const key = assertEnvKey(k, "env key");
assertArg(String(v), `env.${k}`);
assertEnvValue(String(v), `env.${k}`);
return ["--env", `${key}=${v}`];
});
return serialize(() => runCodex(["mcp", "add", n, ...envFlags, "--", cmd, ...cmdArgs]));