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.
| Package | Affected versions | Patched versions |
|---|---|---|
openclawnpm | >= 2026.4.5, < 2026.4.10 | 2026.4.10 |
Affected products
1Patches
1dffad0852920fix: a sandboxed agent can request host node in an ex (#384) (#63880)
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- github.com/advisories/GHSA-736r-jwj6-4w23ghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2026-42434ghsaADVISORY
- github.com/openclaw/openclaw/commit/dffad08529202edbf34e4808788e1182fe10f6a9nvdWEB
- github.com/openclaw/openclaw/pull/63880ghsaWEB
- github.com/openclaw/openclaw/security/advisories/GHSA-736r-jwj6-4w23nvdWEB
- www.vulncheck.com/advisories/openclaw-sandbox-escape-via-host-parameter-override-in-exec-routingnvdWEB
News mentions
0No linked articles in our index yet.