VYPR
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.

PackageAffected versionsPatched versions
openclawnpm
< 2026.2.242026.2.24

Affected products

1

Patches

1
b67e600bff69

fix(security): restrict default safe-bin trusted dirs

https://github.com/openclaw/openclawPeter SteinbergerFeb 24, 2026via ghsa
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

News mentions

0

No linked articles in our index yet.