High severityNVD Advisory· Published Mar 19, 2026· Updated Mar 21, 2026
OpenClaw < 2026.2.24 - Binary Hijacking via Static Default Trusted Directories in safeBins
CVE-2026-32009
Description
OpenClaw versions prior to 2026.2.24 contain a policy bypass vulnerability in the safeBins allowlist evaluation that trusts static default directories including writable package-manager paths like /opt/homebrew/bin and /usr/local/bin. An attacker with write access to these trusted directories can place a malicious binary with the same name as an allowed executable to achieve arbitrary command execution within the OpenClaw runtime context.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
openclawnpm | < 2026.2.24 | 2026.2.24 |
Affected products
1Patches
1b67e600bff69fix(security): restrict default safe-bin trusted dirs
6 files changed · +32 −10
CHANGELOG.md+1 −0 modified@@ -16,6 +16,7 @@ Docs: https://docs.openclaw.ai - Security/Workspace FS: normalize `@`-prefixed paths before workspace-boundary checks (including workspace-only read/write/edit and sandbox mount path guards), preventing absolute-path escape attempts from bypassing guard validation. This ships in the next npm release. Thanks @tdjackey for reporting. - Security/Native images: enforce `tools.fs.workspaceOnly` for native prompt image auto-load (including history refs), preventing out-of-workspace sandbox mounts from being implicitly ingested as vision input. This ships in the next npm release. Thanks @tdjackey for reporting. - Security/Exec approvals: bind `system.run` command display/approval text to full argv when shell-wrapper inline payloads carry positional argv values, and reject payload-only `rawCommand` mismatches for those wrapper-carrier forms, preventing hidden command execution under misleading approval text. This ships in the next npm release. Thanks @tdjackey for reporting. +- Security/Exec: limit default safe-bin trusted directories to immutable system paths (`/bin`, `/usr/bin`) and require explicit opt-in (`tools.exec.safeBinTrustedDirs`) for package-manager/user bin paths (for example Homebrew), preventing writable-dir binary shadowing from auto-satisfying safe-bin allowlist checks. This ships in the next npm release. Thanks @tdjackey for reporting. - Telegram/Media fetch: prioritize IPv4 before IPv6 in SSRF pinned DNS address ordering so media downloads still work on hosts with broken IPv6 routing. (#24295, #23975) Thanks @Glucksberg. - Telegram/Replies: when markdown formatting renders to empty HTML (for example syntax-only chunks in threaded replies), retry delivery with plain text, and fail loud when both formatted and plain payloads are empty to avoid false delivered states. (#25096, #25091) Thanks @Glucksberg. - Sessions/Tool-result guard: avoid generating synthetic `toolResult` entries for assistant turns that ended with `stopReason: "aborted"` or `"error"`, preventing orphaned tool-use IDs from triggering downstream API validation errors. (#25429) Thanks @mikaeldiakhate-cell.
docs/tools/exec-approvals.md+4 −0 modified@@ -165,6 +165,10 @@ and no `$VARS` expansion) for stdin-only segments, so patterns like `*` or `$HOM used to smuggle file reads. Safe bins must also resolve from trusted binary directories (system defaults plus optional `tools.exec.safeBinTrustedDirs`). `PATH` entries are never auto-trusted. +Default trusted safe-bin directories are intentionally minimal: `/bin`, `/usr/bin`. +If your safe-bin executable lives in package-manager/user paths (for example +`/opt/homebrew/bin`, `/usr/local/bin`, `/opt/local/bin`, `/snap/bin`), add them explicitly +to `tools.exec.safeBinTrustedDirs`. Shell chaining and redirections are not auto-allowed in allowlist mode. Shell chaining (`&&`, `||`, `;`) is allowed when every top-level segment satisfies the allowlist
docs/tools/exec.md+1 −1 modified@@ -55,7 +55,7 @@ Notes: - `tools.exec.node` (default: unset) - `tools.exec.pathPrepend`: list of directories to prepend to `PATH` for exec runs (gateway + sandbox only). - `tools.exec.safeBins`: stdin-only safe binaries that can run without explicit allowlist entries. For behavior details, see [Safe bins](/tools/exec-approvals#safe-bins-stdin-only). -- `tools.exec.safeBinTrustedDirs`: additional explicit directories trusted for `safeBins` path checks. `PATH` entries are never auto-trusted. +- `tools.exec.safeBinTrustedDirs`: additional explicit directories trusted for `safeBins` path checks. `PATH` entries are never auto-trusted. Built-in defaults are `/bin` and `/usr/bin`. - `tools.exec.safeBinProfiles`: optional custom argv policy per safe bin (`minPositional`, `maxPositional`, `allowedValueFlags`, `deniedFlags`). Example:
src/infra/exec-safe-bin-runtime-policy.test.ts+14 −0 modified@@ -89,4 +89,18 @@ describe("exec safe-bin runtime policy", () => { expect(policy.trustedSafeBinDirs.has(path.resolve(customDir))).toBe(true); expect(policy.trustedSafeBinDirs.has(path.resolve(agentDir))).toBe(true); }); + + it("does not trust package-manager bin dirs unless explicitly configured", () => { + const defaultPolicy = resolveExecSafeBinRuntimePolicy({}); + expect(defaultPolicy.trustedSafeBinDirs.has(path.resolve("/opt/homebrew/bin"))).toBe(false); + expect(defaultPolicy.trustedSafeBinDirs.has(path.resolve("/usr/local/bin"))).toBe(false); + + const optedIn = resolveExecSafeBinRuntimePolicy({ + global: { + safeBinTrustedDirs: ["/opt/homebrew/bin", "/usr/local/bin"], + }, + }); + expect(optedIn.trustedSafeBinDirs.has(path.resolve("/opt/homebrew/bin"))).toBe(true); + expect(optedIn.trustedSafeBinDirs.has(path.resolve("/usr/local/bin"))).toBe(true); + }); });
src/infra/exec-safe-bin-trust.test.ts+9 −0 modified@@ -8,6 +8,15 @@ import { } from "./exec-safe-bin-trust.js"; describe("exec safe bin trust", () => { + it("keeps default trusted dirs limited to immutable system paths", () => { + const dirs = getTrustedSafeBinDirs({ refresh: true }); + + expect(dirs.has(path.resolve("/bin"))).toBe(true); + expect(dirs.has(path.resolve("/usr/bin"))).toBe(true); + expect(dirs.has(path.resolve("/usr/local/bin"))).toBe(false); + expect(dirs.has(path.resolve("/opt/homebrew/bin"))).toBe(false); + }); + it("builds trusted dirs from defaults and explicit extra dirs", () => { const dirs = buildTrustedSafeBinDirs({ baseDirs: ["/usr/bin"],
src/infra/exec-safe-bin-trust.ts+3 −9 modified@@ -1,14 +1,8 @@ import path from "node:path"; -const DEFAULT_SAFE_BIN_TRUSTED_DIRS = [ - "/bin", - "/usr/bin", - "/usr/local/bin", - "/opt/homebrew/bin", - "/opt/local/bin", - "/snap/bin", - "/run/current-system/sw/bin", -]; +// Keep defaults to OS-managed immutable bins only. +// User/package-manager bins must be opted in via tools.exec.safeBinTrustedDirs. +const DEFAULT_SAFE_BIN_TRUSTED_DIRS = ["/bin", "/usr/bin"]; type TrustedSafeBinDirsParams = { baseDirs?: readonly string[];
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- github.com/openclaw/openclaw/commit/b67e600bff696ff2ed9b470826590c0ce6b3bb0aghsapatchWEB
- github.com/advisories/GHSA-5gj7-jf77-q2q2ghsaADVISORY
- github.com/openclaw/openclaw/security/advisories/GHSA-5gj7-jf77-q2q2ghsathird-party-advisoryWEB
- nvd.nist.gov/vuln/detail/CVE-2026-32009ghsaADVISORY
- www.vulncheck.com/advisories/openclaw-binary-hijacking-via-static-default-trusted-directories-in-safebinsghsathird-party-advisoryWEB
News mentions
0No linked articles in our index yet.