mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-09 07:37:39 +00:00
refactor: tighten safe-bin policy model and docs parity
This commit is contained in:
@@ -519,6 +519,103 @@ describe("exec approvals safe bins", () => {
|
||||
setup?: (cwd: string) => void;
|
||||
};
|
||||
|
||||
function buildDeniedFlagVariantCases(params: {
|
||||
executableName: string;
|
||||
resolvedPath: string;
|
||||
safeBins?: string[];
|
||||
flag: string;
|
||||
takesValue: boolean;
|
||||
label: string;
|
||||
}): SafeBinCase[] {
|
||||
const value = "blocked";
|
||||
const argvVariants: string[][] = [];
|
||||
if (!params.takesValue) {
|
||||
argvVariants.push([params.executableName, params.flag]);
|
||||
} else if (params.flag.startsWith("--")) {
|
||||
argvVariants.push([params.executableName, `${params.flag}=${value}`]);
|
||||
argvVariants.push([params.executableName, params.flag, value]);
|
||||
} else if (params.flag.startsWith("-")) {
|
||||
argvVariants.push([params.executableName, `${params.flag}${value}`]);
|
||||
argvVariants.push([params.executableName, params.flag, value]);
|
||||
} else {
|
||||
argvVariants.push([params.executableName, params.flag, value]);
|
||||
}
|
||||
return argvVariants.map((argv) => ({
|
||||
name: `${params.label} (${argv.slice(1).join(" ")})`,
|
||||
argv,
|
||||
resolvedPath: params.resolvedPath,
|
||||
expected: false,
|
||||
safeBins: params.safeBins ?? [params.executableName],
|
||||
executableName: params.executableName,
|
||||
}));
|
||||
}
|
||||
|
||||
const deniedFlagCases: SafeBinCase[] = [
|
||||
...buildDeniedFlagVariantCases({
|
||||
executableName: "sort",
|
||||
resolvedPath: "/usr/bin/sort",
|
||||
flag: "-o",
|
||||
takesValue: true,
|
||||
label: "blocks sort output flag",
|
||||
}),
|
||||
...buildDeniedFlagVariantCases({
|
||||
executableName: "sort",
|
||||
resolvedPath: "/usr/bin/sort",
|
||||
flag: "--output",
|
||||
takesValue: true,
|
||||
label: "blocks sort output flag",
|
||||
}),
|
||||
...buildDeniedFlagVariantCases({
|
||||
executableName: "sort",
|
||||
resolvedPath: "/usr/bin/sort",
|
||||
flag: "--compress-program",
|
||||
takesValue: true,
|
||||
label: "blocks sort external program flag",
|
||||
}),
|
||||
...buildDeniedFlagVariantCases({
|
||||
executableName: "grep",
|
||||
resolvedPath: "/usr/bin/grep",
|
||||
flag: "-R",
|
||||
takesValue: false,
|
||||
label: "blocks grep recursive flag",
|
||||
}),
|
||||
...buildDeniedFlagVariantCases({
|
||||
executableName: "grep",
|
||||
resolvedPath: "/usr/bin/grep",
|
||||
flag: "--recursive",
|
||||
takesValue: false,
|
||||
label: "blocks grep recursive flag",
|
||||
}),
|
||||
...buildDeniedFlagVariantCases({
|
||||
executableName: "grep",
|
||||
resolvedPath: "/usr/bin/grep",
|
||||
flag: "--file",
|
||||
takesValue: true,
|
||||
label: "blocks grep file-pattern flag",
|
||||
}),
|
||||
...buildDeniedFlagVariantCases({
|
||||
executableName: "jq",
|
||||
resolvedPath: "/usr/bin/jq",
|
||||
flag: "-f",
|
||||
takesValue: true,
|
||||
label: "blocks jq file-program flag",
|
||||
}),
|
||||
...buildDeniedFlagVariantCases({
|
||||
executableName: "jq",
|
||||
resolvedPath: "/usr/bin/jq",
|
||||
flag: "--from-file",
|
||||
takesValue: true,
|
||||
label: "blocks jq file-program flag",
|
||||
}),
|
||||
...buildDeniedFlagVariantCases({
|
||||
executableName: "wc",
|
||||
resolvedPath: "/usr/bin/wc",
|
||||
flag: "--files0-from",
|
||||
takesValue: true,
|
||||
label: "blocks wc file-list flag",
|
||||
}),
|
||||
];
|
||||
|
||||
const cases: SafeBinCase[] = [
|
||||
{
|
||||
name: "allows safe bins with non-path args",
|
||||
@@ -540,54 +637,7 @@ describe("exec approvals safe bins", () => {
|
||||
expected: false,
|
||||
cwd: "/tmp",
|
||||
},
|
||||
{
|
||||
name: "blocks sort output path via -o <file>",
|
||||
argv: ["sort", "-o", "malicious.sh"],
|
||||
resolvedPath: "/usr/bin/sort",
|
||||
expected: false,
|
||||
safeBins: ["sort"],
|
||||
executableName: "sort",
|
||||
},
|
||||
{
|
||||
name: "blocks sort output path via attached short option (-ofile)",
|
||||
argv: ["sort", "-omalicious.sh"],
|
||||
resolvedPath: "/usr/bin/sort",
|
||||
expected: false,
|
||||
safeBins: ["sort"],
|
||||
executableName: "sort",
|
||||
},
|
||||
{
|
||||
name: "blocks sort output path via --output=file",
|
||||
argv: ["sort", "--output=malicious.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 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"],
|
||||
resolvedPath: "/usr/bin/grep",
|
||||
expected: false,
|
||||
safeBins: ["grep"],
|
||||
executableName: "grep",
|
||||
},
|
||||
...deniedFlagCases,
|
||||
{
|
||||
name: "blocks grep file positional when pattern uses -e",
|
||||
argv: ["grep", "-e", "needle", ".env"],
|
||||
@@ -690,13 +740,13 @@ describe("exec approvals safe bins", () => {
|
||||
for (const [name, fixture] of Object.entries(SAFE_BIN_PROFILE_FIXTURES)) {
|
||||
const profile = SAFE_BIN_PROFILES[name];
|
||||
expect(profile).toBeDefined();
|
||||
const fixtureBlockedFlags = fixture.blockedFlags ?? [];
|
||||
const compiledBlockedFlags = profile?.blockedFlags ?? new Set<string>();
|
||||
for (const blockedFlag of fixtureBlockedFlags) {
|
||||
expect(compiledBlockedFlags.has(blockedFlag)).toBe(true);
|
||||
const fixtureDeniedFlags = fixture.deniedFlags ?? [];
|
||||
const compiledDeniedFlags = profile?.deniedFlags ?? new Set<string>();
|
||||
for (const deniedFlag of fixtureDeniedFlags) {
|
||||
expect(compiledDeniedFlags.has(deniedFlag)).toBe(true);
|
||||
}
|
||||
expect(Array.from(compiledBlockedFlags).toSorted()).toEqual(
|
||||
[...fixtureBlockedFlags].toSorted(),
|
||||
expect(Array.from(compiledDeniedFlags).toSorted()).toEqual(
|
||||
[...fixtureDeniedFlags].toSorted(),
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user