From cbe22e1aa8ba43bd0ce6babf19af91ba8326f4fe Mon Sep 17 00:00:00 2001 From: aiirvizionz Date: Sat, 18 Jul 2026 17:11:02 -0600 Subject: [PATCH] fix(mcp): reject empty env and header names --- src/integrations.mjs | 14 ++++++++++++++ test/mcp.test.mjs | 7 +++++++ 2 files changed, 21 insertions(+) diff --git a/src/integrations.mjs b/src/integrations.mjs index ad5659d..f50e7e0 100644 --- a/src/integrations.mjs +++ b/src/integrations.mjs @@ -15,6 +15,11 @@ function splitKV(pair) { return i === -1 ? [String(pair), ""] : [pair.slice(0, i), pair.slice(i + 1)]; } +function headerName(header) { + const i = String(header).indexOf(":"); + return i === -1 ? null : String(header).slice(0, i).trim(); +} + /** Parse `/mcp` tokens (after the `mcp` word) into { list } | { spec } | { error }. */ export function parseMcp(tokens) { const verb = tokens[0]; @@ -45,6 +50,15 @@ export function parseMcp(tokens) { } if (!name) return { error: "missing server name" }; if (!target) return { error: "missing server URL or command" }; + if (env.some(([key]) => String(key).trim() === "")) { + return { error: "mcp --env requires a non-empty key" }; + } + if (headers.some((header) => headerName(header) === null)) { + return { error: "mcp --header requires a Name: Value header" }; + } + if (headers.some((header) => headerName(header) === "")) { + return { error: "mcp --header requires a non-empty header name" }; + } return { spec: { name, target, args, transport, env, headers } }; } diff --git a/test/mcp.test.mjs b/test/mcp.test.mjs index 21c7958..bd0a6eb 100644 --- a/test/mcp.test.mjs +++ b/test/mcp.test.mjs @@ -77,6 +77,13 @@ test("parseMcp: a stdio install without a name errors", () => { assert.ok(parseMcp(["bogus"]).error); }); +test("parseMcp: env and header flags reject empty names", () => { + assert.match(parseMcp(["install", "https://x.dev/mcp", "--env", "=secret"]).error, /--env requires a non-empty key/); + assert.match(parseMcp(["install", "https://x.dev/mcp", "--header", ": Bearer token"]).error, /--header requires a non-empty header name/); + assert.match(parseMcp(["install", "https://x.dev/mcp", "--header", "Authorization"]).error, /--header requires a Name: Value header/); + assert.deepEqual(parseMcp(["install", "https://x.dev/mcp", "--env", "EMPTY="]).spec.env, [["EMPTY", ""]]); +}); + test("runMcpAdd summarizes added / skipped / not-installed", async () => { const spec = { name: "s", target: "https://x.dev/mcp", env: [], headers: ["A: b"] }; const plan = planMcpAdd(spec, { installedSet: new Set(["claude", "opencode"]) }); // gemini/codex not installed; codex also skips