do not auto-approve the find command if it contains options that write files or spawn commands (#482)
Updates `isSafeCommand()` so that an invocation of `find` is not auto-approved if it contains any of: `-exec`, `-execdir`, `-ok`, `-okdir`, `-delete`, `-fls`, `-fprint`, `-fprint0`, `-fprintf`.
This commit is contained in:
@@ -329,11 +329,20 @@ export function isSafeCommand(
|
||||
reason: "Ripgrep search",
|
||||
group: "Searching",
|
||||
};
|
||||
case "find":
|
||||
return {
|
||||
reason: "Find files or directories",
|
||||
group: "Searching",
|
||||
};
|
||||
case "find": {
|
||||
// Certain options to `find` allow executing arbitrary processes, so we
|
||||
// cannot auto-approve them.
|
||||
if (
|
||||
command.some((arg: string) => UNSAFE_OPTIONS_FOR_FIND_COMMAND.has(arg))
|
||||
) {
|
||||
break;
|
||||
} else {
|
||||
return {
|
||||
reason: "Find files or directories",
|
||||
group: "Searching",
|
||||
};
|
||||
}
|
||||
}
|
||||
case "grep":
|
||||
return {
|
||||
reason: "Text search (grep)",
|
||||
@@ -421,6 +430,21 @@ function isValidSedNArg(arg: string | undefined): boolean {
|
||||
return arg != null && /^(\d+,)?\d+p$/.test(arg);
|
||||
}
|
||||
|
||||
const UNSAFE_OPTIONS_FOR_FIND_COMMAND: ReadonlySet<string> = new Set([
|
||||
// Options that can execute arbitrary commands.
|
||||
"-exec",
|
||||
"-execdir",
|
||||
"-ok",
|
||||
"-okdir",
|
||||
// Option that deletes matching files.
|
||||
"-delete",
|
||||
// Options that write pathnames to a file.
|
||||
"-fls",
|
||||
"-fprint",
|
||||
"-fprint0",
|
||||
"-fprintf",
|
||||
]);
|
||||
|
||||
// ---------------- Helper utilities for complex shell expressions -----------------
|
||||
|
||||
// A conservative allow-list of bash operators that do not, on their own, cause
|
||||
|
||||
@@ -89,4 +89,56 @@ describe("canAutoApprove()", () => {
|
||||
|
||||
expect(check(["cargo", "build"])).toEqual({ type: "ask-user" });
|
||||
});
|
||||
|
||||
test("find", () => {
|
||||
expect(check(["find", ".", "-name", "file.txt"])).toEqual({
|
||||
type: "auto-approve",
|
||||
reason: "Find files or directories",
|
||||
group: "Searching",
|
||||
runInSandbox: false,
|
||||
});
|
||||
|
||||
// Options that can execute arbitrary commands.
|
||||
expect(
|
||||
check(["find", ".", "-name", "file.txt", "-exec", "rm", "{}", ";"]),
|
||||
).toEqual({
|
||||
type: "ask-user",
|
||||
});
|
||||
expect(
|
||||
check(["find", ".", "-name", "*.py", "-execdir", "python3", "{}", ";"]),
|
||||
).toEqual({
|
||||
type: "ask-user",
|
||||
});
|
||||
expect(
|
||||
check(["find", ".", "-name", "file.txt", "-ok", "rm", "{}", ";"]),
|
||||
).toEqual({
|
||||
type: "ask-user",
|
||||
});
|
||||
expect(
|
||||
check(["find", ".", "-name", "*.py", "-okdir", "python3", "{}", ";"]),
|
||||
).toEqual({
|
||||
type: "ask-user",
|
||||
});
|
||||
|
||||
// Option that deletes matching files.
|
||||
expect(check(["find", ".", "-delete", "-name", "file.txt"])).toEqual({
|
||||
type: "ask-user",
|
||||
});
|
||||
|
||||
// Options that write pathnames to a file.
|
||||
expect(check(["find", ".", "-fls", "/etc/passwd"])).toEqual({
|
||||
type: "ask-user",
|
||||
});
|
||||
expect(check(["find", ".", "-fprint", "/etc/passwd"])).toEqual({
|
||||
type: "ask-user",
|
||||
});
|
||||
expect(check(["find", ".", "-fprint0", "/etc/passwd"])).toEqual({
|
||||
type: "ask-user",
|
||||
});
|
||||
expect(
|
||||
check(["find", ".", "-fprintf", "/root/suid.txt", "%#m %u %p\n"]),
|
||||
).toEqual({
|
||||
type: "ask-user",
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user