VYPR
High severity8.8GHSA Advisory· Published May 5, 2026· Updated May 5, 2026

CVE-2026-42434

CVE-2026-42434

Description

OpenClaw versions 2026.4.5 before 2026.4.10 contain a sandbox escape vulnerability allowing sandboxed agents to override exec routing by specifying host=node. Attackers can bypass sandbox boundaries and route execution to remote nodes instead of intended sandbox paths.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
openclawnpm
>= 2026.4.5, < 2026.4.102026.4.10

Affected products

1

Patches

1
dffad0852920

fix: a sandboxed agent can request host node in an ex (#384) (#63880)

https://github.com/openclaw/openclawDevin RobisonApr 10, 2026via ghsa
5 files changed · +91 16
  • CHANGELOG.md+1 0 modified
    @@ -116,6 +116,7 @@ Docs: https://docs.openclaw.ai
     - Matrix/migration: keep packaged warning-only crypto migrations from being misclassified as actionable when only helper chunks are present, so startup and doctor stay on the warning-only path instead of creating unnecessary migration snapshots. (#64373) Thanks @gumadeiras.
     - Matrix/ACP thread bindings: preserve canonical room casing and parent conversation routing during ACP session spawn so mixed-case room ids bind correctly from top-level rooms and existing Matrix threads. (#64343) Thanks @gumadeiras.
     - Agents/subagents: deduplicate delivered completion announces so retry or re-entry cleanup does not inject duplicate internal-context completion turns into the parent session. (#61525) Thanks @100yenadmin.
    +- Agents/exec: keep sandboxed `tools.exec.host=auto` sessions from honoring per-call `host=node` or `host=gateway` overrides while a sandbox runtime is active, and stop advertising node routing in that state so exec stays on the sandbox host. (#63880)
     
     ## 2026.4.9
     
    
  • src/agents/bash-tools.exec-runtime.test.ts+14 1 modified
    @@ -127,7 +127,20 @@ describe("resolveExecTarget", () => {
             sandboxAvailable: true,
           }),
         ).toThrow(
    -      "exec host not allowed (requested gateway; configured host is auto; set tools.exec.host=gateway or auto to allow this override).",
    +      "exec host not allowed (requested gateway; configured host is auto; set tools.exec.host=gateway to allow this override).",
    +    );
    +  });
    +
    +  it("rejects per-call host=node override from auto when sandbox is available", () => {
    +    expect(() =>
    +      resolveExecTarget({
    +        configuredTarget: "auto",
    +        requestedTarget: "node",
    +        elevatedRequested: false,
    +        sandboxAvailable: true,
    +      }),
    +    ).toThrow(
    +      "exec host not allowed (requested node; configured host is auto; set tools.exec.host=node to allow this override).",
         );
       });
     
    
  • src/agents/bash-tools.exec-runtime.ts+11 4 modified
    @@ -228,7 +228,10 @@ export function isRequestedExecTargetAllowed(params: {
         return true;
       }
       if (params.configuredTarget === "auto") {
    -    if (params.sandboxAvailable && params.requestedTarget === "gateway") {
    +    if (
    +      params.sandboxAvailable &&
    +      (params.requestedTarget === "gateway" || params.requestedTarget === "node")
    +    ) {
           return false;
         }
         return true;
    @@ -254,9 +257,13 @@ export function resolveExecTarget(params: {
       ) {
         const allowedConfig = Array.from(
           new Set(
    -        requestedTarget === "gateway" && !params.sandboxAvailable
    -          ? ["gateway", "auto"]
    -          : [renderExecTargetLabel(requestedTarget), "auto"],
    +        configuredTarget === "auto" &&
    +          params.sandboxAvailable &&
    +          (requestedTarget === "gateway" || requestedTarget === "node")
    +          ? [renderExecTargetLabel(requestedTarget)]
    +          : requestedTarget === "gateway" && !params.sandboxAvailable
    +            ? ["gateway", "auto"]
    +            : [renderExecTargetLabel(requestedTarget), "auto"],
           ),
         ).join(" or ");
         throw new Error(
    
  • src/agents/exec-defaults.test.ts+36 2 modified
    @@ -1,7 +1,7 @@
     import { beforeEach, describe, expect, it, vi } from "vitest";
     import type { SessionEntry } from "../config/sessions.js";
     import * as execApprovals from "../infra/exec-approvals.js";
    -import { resolveExecDefaults } from "./exec-defaults.js";
    +import { canExecRequestNode, resolveExecDefaults } from "./exec-defaults.js";
     
     describe("resolveExecDefaults", () => {
       beforeEach(() => {
    @@ -27,7 +27,7 @@ describe("resolveExecDefaults", () => {
         ).toBe(false);
       });
     
    -  it("keeps node routing available when exec host is auto", () => {
    +  it("does not advertise node routing when exec host is auto and sandbox is available", () => {
         expect(
           resolveExecDefaults({
             cfg: {
    @@ -42,6 +42,25 @@ describe("resolveExecDefaults", () => {
         ).toMatchObject({
           host: "auto",
           effectiveHost: "sandbox",
    +      canRequestNode: false,
    +    });
    +  });
    +
    +  it("keeps node routing available when exec host is auto without sandbox", () => {
    +    expect(
    +      resolveExecDefaults({
    +        cfg: {
    +          tools: {
    +            exec: {
    +              host: "auto",
    +            },
    +          },
    +        },
    +        sandboxAvailable: false,
    +      }),
    +    ).toMatchObject({
    +      host: "auto",
    +      effectiveHost: "gateway",
           canRequestNode: true,
         });
       });
    @@ -104,4 +123,19 @@ describe("resolveExecDefaults", () => {
           ask: "off",
         });
       });
    +
    +  it("blocks node advertising in helper calls when sandbox is available", () => {
    +    expect(
    +      canExecRequestNode({
    +        cfg: {
    +          tools: {
    +            exec: {
    +              host: "auto",
    +            },
    +          },
    +        },
    +        sandboxAvailable: true,
    +      }),
    +    ).toBe(false);
    +  });
     });
    
  • src/agents/exec-defaults.ts+29 9 modified
    @@ -53,16 +53,38 @@ function resolveExecConfigState(params: {
       };
     }
     
    +function resolveExecSandboxAvailability(params: {
    +  cfg: OpenClawConfig;
    +  sessionKey?: string;
    +  sandboxAvailable?: boolean;
    +}) {
    +  return (
    +    params.sandboxAvailable ??
    +    (params.sessionKey
    +      ? resolveSandboxRuntimeStatus({
    +          cfg: params.cfg,
    +          sessionKey: params.sessionKey,
    +        }).sandboxed
    +      : false)
    +  );
    +}
    +
     export function canExecRequestNode(params: {
       cfg?: OpenClawConfig;
       sessionEntry?: SessionEntry;
       agentId?: string;
       sessionKey?: string;
    +  sandboxAvailable?: boolean;
     }): boolean {
    -  const { host } = resolveExecConfigState(params);
    +  const { cfg, host } = resolveExecConfigState(params);
       return isRequestedExecTargetAllowed({
         configuredTarget: host,
         requestedTarget: "node",
    +    sandboxAvailable: resolveExecSandboxAvailability({
    +      cfg,
    +      sessionKey: params.sessionKey,
    +      sandboxAvailable: params.sandboxAvailable,
    +    }),
       });
     }
     
    @@ -81,14 +103,11 @@ export function resolveExecDefaults(params: {
       canRequestNode: boolean;
     } {
       const { cfg, host, agentExec, globalExec } = resolveExecConfigState(params);
    -  const sandboxAvailable =
    -    params.sandboxAvailable ??
    -    (params.sessionKey
    -      ? resolveSandboxRuntimeStatus({
    -          cfg,
    -          sessionKey: params.sessionKey,
    -        }).sandboxed
    -      : false);
    +  const sandboxAvailable = resolveExecSandboxAvailability({
    +    cfg,
    +    sessionKey: params.sessionKey,
    +    sandboxAvailable: params.sandboxAvailable,
    +  });
       const resolved = resolveExecTarget({
         configuredTarget: host,
         elevatedRequested: false,
    @@ -115,6 +134,7 @@ export function resolveExecDefaults(params: {
         canRequestNode: isRequestedExecTargetAllowed({
           configuredTarget: host,
           requestedTarget: "node",
    +      sandboxAvailable,
         }),
       };
     }
    

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

6

News mentions

0

No linked articles in our index yet.