Skip to content

Commit e57b944

Browse files
Fix auto-mode allow of bash combined file redirects (#905)
Bash combined redirects write a file the same way a plain redirect does. The matcher skipped every form that started with >& so it would not flag fd dups, and those writes auto-allowed. Classify >& to a non-fd, non-safe-sink path as a file mutation and leave fd dups unmatched.
1 parent 22aaf8c commit e57b944

2 files changed

Lines changed: 29 additions & 0 deletions

File tree

src/permission/auto-shell-policy.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,9 @@ export const AUTO_SHELL_RULES: AutoShellRule[] = [
121121
// trailing `|` as in `>|` / `>>|`) to a target that is not an fd dup
122122
// (`2>&1`) or a safe pseudo-device (`> /dev/null`, a TTY).
123123
/[0-9]?>>?\|?\s*(?!&|\/dev\/(?:null|stdout|stderr|stdin|tty|pts\/|fd\/))[^\s|;&)]/,
124+
// bash `>& word` is `>word 2>&1` when word is not an fd number or `-`.
125+
// `2>&1` and `n>&-` stay unmatched; `>& /dev/null` stays a safe sink.
126+
/[0-9]?>&\s*(?!(?:[0-9]+|-|\/dev\/(?:null|stdout|stderr|stdin|tty|pts\/|fd\/)\S*)(?:\s|$|[|;&)]))[^\s|;&)]/,
124127
// tee writes its stdin to one or more files.
125128
/(?:^|[\n;&|({]\s*)tee\b/,
126129
// In-place stream editors: sed -i, perl -pi -e, ruby -i.

src/permission/classify-security.test.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -962,6 +962,32 @@ describe("CL-6702 — bash clobber redirects match file-mutation", () => {
962962
});
963963
});
964964

965+
describe("bash >& file redirects match file-mutation", () => {
966+
test("echo hi >& out.txt denies", () => {
967+
expect(autoShellRuleForCall(shellCall("echo hi >& out.txt"))?.name).toBe(
968+
"file-mutation",
969+
);
970+
});
971+
972+
test("echo hi >&file denies", () => {
973+
expect(autoShellRuleForCall(shellCall("echo hi >&file"))?.name).toBe(
974+
"file-mutation",
975+
);
976+
});
977+
978+
test("echo hi > out.txt still denies", () => {
979+
expect(autoShellRuleForCall(shellCall("echo hi > out.txt"))?.name).toBe(
980+
"file-mutation",
981+
);
982+
});
983+
984+
test("echo hi 2>&1 is not a file-mutation deny", () => {
985+
expect(autoShellRuleForCall(shellCall("echo hi 2>&1"))?.name).not.toBe(
986+
"file-mutation",
987+
);
988+
});
989+
});
990+
965991
describe("CL-6697 — quoted dangerous flags and program names still deny/ask", () => {
966992
test("a quoted -c interpreter one-liner denies", () => {
967993
expect(

0 commit comments

Comments
 (0)