VYPR
Moderate severityNVD Advisory· Published Mar 19, 2026· Updated Mar 20, 2026

OpenClaw < 2026.2.22 - Allowlist Bypass via sort --compress-program Parameter

CVE-2026-32010

Description

OpenClaw versions prior to 2026.2.22 contain an allowlist bypass vulnerability in the safe-bin configuration when sort is manually added to tools.exec.safeBins. Attackers can invoke sort with the --compress-program flag to execute arbitrary external programs without operator approval in allowlist mode with ask=on-miss enabled.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
openclawnpm
< 2026.2.222026.2.22

Affected products

1

Patches

1
57fbbaebca4d

fix: block safeBins sort --compress-program bypass

https://github.com/openclaw/openclawPeter SteinbergerFeb 21, 2026via ghsa
6 files changed · +54 4
  • CHANGELOG.md+1 0 modified
    @@ -32,6 +32,7 @@ Docs: https://docs.openclaw.ai
     
     ### Fixes
     
    +- Security/Exec: block `sort --compress-program` in `tools.exec.safeBins` policy so allowlist-mode safe-bin checks cannot be used to bypass approval and spawn external programs. Thanks @tdjackey for reporting.
     - Doctor/State integrity: only require/create the OAuth credentials directory when WhatsApp or pairing-backed channels are configured, and downgrade fresh-install missing-dir noise to an informational warning.
     - Security/Agents: cap embedded Pi runner outer retry loop with a higher profile-aware dynamic limit (32-160 attempts) and return an explicit `retry_limit` error payload when retries never converge, preventing unbounded internal retry cycles (`GHSA-76m6-pj3w-v7mf`).
     - Telegram: detect duplicate bot-token ownership across Telegram accounts at startup/status time, mark secondary accounts as not configured with an explicit fix message, and block duplicate account startup before polling to avoid endless `getUpdates` conflict loops.
    
  • docs/tools/exec-approvals.md+3 2 modified
    @@ -127,9 +127,10 @@ positional file args and path-like tokens, so they can only operate on the incom
     Validation is deterministic from argv shape only (no host filesystem existence checks), which
     prevents file-existence oracle behavior from allow/deny differences.
     File-oriented options are denied for default safe bins (for example `sort -o`, `sort --output`,
    -`sort --files0-from`, `wc --files0-from`, `jq -f/--from-file`, `grep -f/--file`).
    +`sort --files0-from`, `sort --compress-program`, `wc --files0-from`, `jq -f/--from-file`,
    +`grep -f/--file`).
     Safe bins also enforce explicit per-binary flag policy for options that break stdin-only
    -behavior (for example `sort -o/--output` and grep recursive flags).
    +behavior (for example `sort -o/--output/--compress-program` and grep recursive flags).
     Safe bins also force argv tokens to be treated as **literal text** at execution time (no globbing
     and no `$VARS` expansion) for stdin-only segments, so patterns like `*` or `$HOME/...` cannot be
     used to smuggle file reads.
    
  • src/agents/pi-tools.safe-bins.e2e.test.ts+18 0 modified
    @@ -222,6 +222,24 @@ describe("createOpenClawCodingTools safeBins", () => {
         }
       });
     
    +  it("blocks sort --compress-program from bypassing safeBins", async () => {
    +    if (process.platform === "win32") {
    +      return;
    +    }
    +
    +    const { tmpDir, execTool } = await createSafeBinsExecTool({
    +      tmpPrefix: "openclaw-safe-bins-sort-compress-",
    +      safeBins: ["sort"],
    +    });
    +
    +    await expect(
    +      execTool.execute("call1", {
    +        command: "sort --compress-program=sh",
    +        workdir: tmpDir,
    +      }),
    +    ).rejects.toThrow("exec denied: allowlist miss");
    +  });
    +
       it("blocks shell redirection metacharacters in safeBins mode", async () => {
         if (process.platform === "win32") {
           return;
    
  • src/infra/exec-approvals.test.ts+16 0 modified
    @@ -564,6 +564,22 @@ describe("exec approvals safe bins", () => {
           safeBins: ["sort"],
           executableName: "sort",
         },
    +    {
    +      name: "blocks sort external program flag via --compress-program=<prog>",
    +      argv: ["sort", "--compress-program=sh"],
    +      resolvedPath: "/usr/bin/sort",
    +      expected: false,
    +      safeBins: ["sort"],
    +      executableName: "sort",
    +    },
    +    {
    +      name: "blocks sort external program flag via --compress-program <prog>",
    +      argv: ["sort", "--compress-program", "sh"],
    +      resolvedPath: "/usr/bin/sort",
    +      expected: false,
    +      safeBins: ["sort"],
    +      executableName: "sort",
    +    },
         {
           name: "blocks grep recursive flags that read cwd",
           argv: ["grep", "-R", "needle"],
    
  • src/infra/exec-safe-bin-policy.test.ts+14 0 modified
    @@ -20,3 +20,17 @@ describe("exec safe bin policy grep", () => {
         expect(validateSafeBinArgv(["-e", "KEY", "--", ".env"], grepProfile)).toBe(false);
       });
     });
    +
    +describe("exec safe bin policy sort", () => {
    +  const sortProfile = SAFE_BIN_PROFILES.sort;
    +
    +  it("allows stdin-only sort flags", () => {
    +    expect(validateSafeBinArgv(["-S", "1M"], sortProfile)).toBe(true);
    +    expect(validateSafeBinArgv(["--key=1,1"], sortProfile)).toBe(true);
    +  });
    +
    +  it("blocks sort --compress-program in safe-bin mode", () => {
    +    expect(validateSafeBinArgv(["--compress-program=sh"], sortProfile)).toBe(false);
    +    expect(validateSafeBinArgv(["--compress-program", "sh"], sortProfile)).toBe(false);
    +  });
    +});
    
  • src/infra/exec-safe-bin-policy.ts+2 2 modified
    @@ -151,7 +151,6 @@ export const SAFE_BIN_PROFILE_FIXTURES: Record<string, SafeBinProfileFixture> =
           "--field-separator",
           "--buffer-size",
           "--temporary-directory",
    -      "--compress-program",
           "--parallel",
           "--batch-size",
           "--random-source",
    @@ -163,7 +162,8 @@ export const SAFE_BIN_PROFILE_FIXTURES: Record<string, SafeBinProfileFixture> =
           "-T",
           "-o",
         ],
    -    blockedFlags: ["--files0-from", "--output", "-o"],
    +    // --compress-program can invoke an external executable and breaks stdin-only guarantees.
    +    blockedFlags: ["--compress-program", "--files0-from", "--output", "-o"],
       },
       uniq: {
         maxPositional: 0,
    

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.