fix: block safeBins sort --compress-program bypass

This commit is contained in:
Peter Steinberger
2026-02-21 19:13:53 +01:00
parent bdfb97afad
commit 57fbbaebca
6 changed files with 54 additions and 4 deletions

View File

@@ -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;

View File

@@ -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"],

View File

@@ -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);
});
});

View File

@@ -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,