VYPR
High severity7.8NVD Advisory· Published Apr 28, 2026· Updated May 1, 2026

CVE-2026-41384

CVE-2026-41384

Description

OpenClaw before 2026.3.24 contains an environment variable injection vulnerability in the CLI backend runner that allows attackers to inject malicious environment variables through workspace configuration. Attackers can craft malicious workspace configs to inject arbitrary environment variables into the backend process spawning, enabling code execution or sensitive data exposure.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
openclawnpm
< 2026.3.242026.3.24

Affected products

1
  • cpe:2.3:a:openclaw:openclaw:*:*:*:*:*:node.js:*:*
    Range: <2026.3.24

Patches

1
c2fb7f1948c3

Adjust CLI backend environment handling before spawn (#53921)

https://github.com/openclaw/openclawDevin RobisonMar 24, 2026via ghsa
2 files changed · +117 2
  • src/agents/cli-runner.test.ts+111 1 modified
    @@ -1,7 +1,7 @@
     import fs from "node:fs/promises";
     import os from "node:os";
     import path from "node:path";
    -import { beforeEach, describe, expect, it, vi } from "vitest";
    +import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
     import type { OpenClawConfig } from "../config/config.js";
     import { resolveCliNoOutputTimeoutMs } from "./cli-runner/helpers.js";
     import type { EmbeddedContextFile } from "./pi-embedded-helpers.js";
    @@ -102,6 +102,10 @@ function createManagedRun(exit: MockRunExit, pid = 1234) {
     }
     
     describe("runCliAgent with process supervisor", () => {
    +  afterEach(() => {
    +    vi.unstubAllEnvs();
    +  });
    +
       beforeEach(async () => {
         supervisorSpawnMock.mockClear();
         enqueueSystemEventMock.mockClear();
    @@ -157,6 +161,112 @@ describe("runCliAgent with process supervisor", () => {
         expect(input.scopeKey).toContain("thread-123");
       });
     
    +  it("sanitizes dangerous backend env overrides before spawn", async () => {
    +    vi.stubEnv("PATH", "/usr/bin:/bin");
    +    vi.stubEnv("HOME", "/tmp/trusted-home");
    +
    +    supervisorSpawnMock.mockResolvedValueOnce(
    +      createManagedRun({
    +        reason: "exit",
    +        exitCode: 0,
    +        exitSignal: null,
    +        durationMs: 50,
    +        stdout: "ok",
    +        stderr: "",
    +        timedOut: false,
    +        noOutputTimedOut: false,
    +      }),
    +    );
    +
    +    await runCliAgent({
    +      sessionId: "s1",
    +      sessionFile: "/tmp/session.jsonl",
    +      workspaceDir: "/tmp",
    +      config: {
    +        agents: {
    +          defaults: {
    +            cliBackends: {
    +              "codex-cli": {
    +                env: {
    +                  NODE_OPTIONS: "--require ./malicious.js",
    +                  LD_PRELOAD: "/tmp/pwn.so",
    +                  PATH: "/tmp/evil",
    +                  HOME: "/tmp/evil-home",
    +                  SAFE_KEY: "ok",
    +                },
    +              },
    +            },
    +          },
    +        },
    +      } satisfies OpenClawConfig,
    +      prompt: "hi",
    +      provider: "codex-cli",
    +      model: "gpt-5.2-codex",
    +      timeoutMs: 1_000,
    +      runId: "run-env-sanitized",
    +      cliSessionId: "thread-123",
    +    });
    +
    +    const input = supervisorSpawnMock.mock.calls[0]?.[0] as {
    +      env?: Record<string, string | undefined>;
    +    };
    +    expect(input.env?.SAFE_KEY).toBe("ok");
    +    expect(input.env?.PATH).toBe("/usr/bin:/bin");
    +    expect(input.env?.HOME).toBe("/tmp/trusted-home");
    +    expect(input.env?.NODE_OPTIONS).toBeUndefined();
    +    expect(input.env?.LD_PRELOAD).toBeUndefined();
    +  });
    +
    +  it("applies clearEnv after sanitizing backend env overrides", async () => {
    +    vi.stubEnv("PATH", "/usr/bin:/bin");
    +    vi.stubEnv("SAFE_CLEAR", "from-base");
    +
    +    supervisorSpawnMock.mockResolvedValueOnce(
    +      createManagedRun({
    +        reason: "exit",
    +        exitCode: 0,
    +        exitSignal: null,
    +        durationMs: 50,
    +        stdout: "ok",
    +        stderr: "",
    +        timedOut: false,
    +        noOutputTimedOut: false,
    +      }),
    +    );
    +
    +    await runCliAgent({
    +      sessionId: "s1",
    +      sessionFile: "/tmp/session.jsonl",
    +      workspaceDir: "/tmp",
    +      config: {
    +        agents: {
    +          defaults: {
    +            cliBackends: {
    +              "codex-cli": {
    +                env: {
    +                  SAFE_KEEP: "keep-me",
    +                },
    +                clearEnv: ["SAFE_CLEAR"],
    +              },
    +            },
    +          },
    +        },
    +      } satisfies OpenClawConfig,
    +      prompt: "hi",
    +      provider: "codex-cli",
    +      model: "gpt-5.2-codex",
    +      timeoutMs: 1_000,
    +      runId: "run-clear-env",
    +      cliSessionId: "thread-123",
    +    });
    +
    +    const input = supervisorSpawnMock.mock.calls[0]?.[0] as {
    +      env?: Record<string, string | undefined>;
    +    };
    +    expect(input.env?.SAFE_KEEP).toBe("keep-me");
    +    expect(input.env?.SAFE_CLEAR).toBeUndefined();
    +  });
    +
       it("prepends bootstrap warnings to the CLI prompt body", async () => {
         supervisorSpawnMock.mockResolvedValueOnce(
           createManagedRun({
    
  • src/agents/cli-runner.ts+6 1 modified
    @@ -5,6 +5,7 @@ import type { OpenClawConfig } from "../config/config.js";
     import { shouldLogVerbose } from "../globals.js";
     import { isTruthyEnvValue } from "../infra/env.js";
     import { requestHeartbeatNow } from "../infra/heartbeat-wake.js";
    +import { sanitizeHostExecEnv } from "../infra/host-env-security.js";
     import { enqueueSystemEvent } from "../infra/system-events.js";
     import { createSubsystemLogger } from "../logging/subsystem.js";
     import { getProcessSupervisor } from "../process/supervisor/index.js";
    @@ -296,7 +297,11 @@ export async function runCliAgent(params: {
             }
     
             const env = (() => {
    -          const next = { ...process.env, ...backend.env };
    +          const next = sanitizeHostExecEnv({
    +            baseEnv: process.env,
    +            overrides: backend.env,
    +            blockPathOverrides: true,
    +          });
               for (const key of backend.clearEnv ?? []) {
                 delete next[key];
               }
    

Vulnerability mechanics

Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

5

News mentions

0

No linked articles in our index yet.