High severity7.3NVD Advisory· Published May 11, 2026· Updated May 13, 2026
CVE-2026-44995
CVE-2026-44995
Description
OpenClaw before 2026.4.20 contains an improper environment variable validation vulnerability in MCP stdio server configuration that allows attackers to execute arbitrary code. Malicious workspace configurations can pass dangerous startup variables like NODE_OPTIONS, LD_PRELOAD, or BASH_ENV to spawned MCP server processes, enabling code injection when operators start sessions using those servers.
Affected products
1Patches
162fa5071896efix(mcp): block dangerous stdio env overrides
3 files changed · +83 −4
src/agents/mcp-config-shared.ts+32 −2 modified@@ -1,16 +1,28 @@ +import { + isDangerousHostEnvOverrideVarName, + isDangerousHostEnvVarName, +} from "../infra/host-env-security.js"; + export function isMcpConfigRecord(value: unknown): value is Record<string, unknown> { return value !== null && typeof value === "object" && !Array.isArray(value); } -export function toMcpStringRecord( +function toMcpFilteredStringRecord( value: unknown, - options?: { onDroppedEntry?: (key: string, value: unknown) => void }, + options?: { + onDroppedEntry?: (key: string, value: unknown) => void; + shouldDropKey?: (key: string) => boolean; + }, ): Record<string, string> | undefined { if (!isMcpConfigRecord(value)) { return undefined; } const entries = Object.entries(value) .map(([key, entry]) => { + if (options?.shouldDropKey?.(key)) { + options?.onDroppedEntry?.(key, entry); + return null; + } if (typeof entry === "string") { return [key, entry] as const; } @@ -24,6 +36,24 @@ export function toMcpStringRecord( return entries.length > 0 ? Object.fromEntries(entries) : undefined; } +export function toMcpStringRecord( + value: unknown, + options?: { onDroppedEntry?: (key: string, value: unknown) => void }, +): Record<string, string> | undefined { + return toMcpFilteredStringRecord(value, options); +} + +export function toMcpEnvRecord( + value: unknown, + options?: { onDroppedEntry?: (key: string, value: unknown) => void }, +): Record<string, string> | undefined { + return toMcpFilteredStringRecord(value, { + ...options, + shouldDropKey: (key) => + isDangerousHostEnvVarName(key) || isDangerousHostEnvOverrideVarName(key), + }); +} + export function toMcpStringArray(value: unknown): string[] | undefined { if (!Array.isArray(value)) { return undefined;
src/agents/mcp-stdio.ts+2 −2 modified@@ -1,4 +1,4 @@ -import { isMcpConfigRecord, toMcpStringArray, toMcpStringRecord } from "./mcp-config-shared.js"; +import { isMcpConfigRecord, toMcpEnvRecord, toMcpStringArray } from "./mcp-config-shared.js"; type StdioMcpServerLaunchConfig = { command: string; @@ -35,7 +35,7 @@ export function resolveStdioMcpServerLaunchConfig(raw: unknown): StdioMcpServerL config: { command: raw.command, args: toMcpStringArray(raw.args), - env: toMcpStringRecord(raw.env), + env: toMcpEnvRecord(raw.env), cwd, }, };
src/agents/mcp-transport-config.test.ts+49 −0 modified@@ -18,6 +18,35 @@ describe("resolveMcpTransportConfig", () => { }); }); + it("drops dangerous env overrides from stdio config", () => { + const resolved = resolveMcpTransportConfig("probe", { + command: "node", + env: { + SAFE_VALUE: "ok", + PORT: 3000, + ENABLED: true, + NODE_OPTIONS: "--require=./evil.js", + LD_PRELOAD: "/tmp/pwn.so", + BASH_ENV: "/tmp/pwn.sh", + }, + }); + + expect(resolved).toEqual({ + kind: "stdio", + transportType: "stdio", + command: "node", + args: undefined, + env: { + SAFE_VALUE: "ok", + PORT: "3000", + ENABLED: "true", + }, + cwd: undefined, + description: "node", + connectionTimeoutMs: 30_000, + }); + }); + it("resolves SSE config by default", () => { const resolved = resolveMcpTransportConfig("probe", { url: "https://mcp.example.com/sse", @@ -40,6 +69,26 @@ describe("resolveMcpTransportConfig", () => { }); }); + it("keeps HTTP header parsing unchanged for env-like names", () => { + const resolved = resolveMcpTransportConfig("probe", { + url: "https://mcp.example.com/sse", + headers: { + NODE_OPTIONS: "allowed-header", + }, + }); + + expect(resolved).toEqual({ + kind: "http", + transportType: "sse", + url: "https://mcp.example.com/sse", + headers: { + NODE_OPTIONS: "allowed-header", + }, + description: "https://mcp.example.com/sse", + connectionTimeoutMs: 30_000, + }); + }); + it("resolves explicit streamable HTTP config", () => { const resolved = resolveMcpTransportConfig("probe", { url: "https://mcp.example.com/http",
Vulnerability mechanics
AI mechanics synthesis has not run for this CVE yet.
References
4- github.com/openclaw/openclaw/commit/62fa5071896e95edc7f67d1cebc70a2859e283afnvdPatch
- github.com/openclaw/openclaw/security/advisories/GHSA-mj59-h3q9-ghfhnvdThird Party Advisory
- www.vulncheck.com/advisories/openclaw-arbitrary-code-execution-via-mcp-stdio-environment-variablesnvdThird Party AdvisoryPatch
- github.com/openclaw/openclaw/commit/85d86ebc4bf3d2226d39d132a484f4f7a299fa1bnvdBroken Link
News mentions
0No linked articles in our index yet.