Skip to content

Fix auto-mode allowing quoted shell redirect writes and dangerous flags - #601

Merged
TheGreatAxios merged 3 commits into
mainfrom
cl-6703-fix-auto-mode-allowing-quoted-shell-redirect-writes
Aug 24, 2026
Merged

Fix auto-mode allowing quoted shell redirect writes and dangerous flags#601
TheGreatAxios merged 3 commits into
mainfrom
cl-6703-fix-auto-mode-allowing-quoted-shell-redirect-writes

Conversation

@TheGreatAxios

Copy link
Copy Markdown
Collaborator

Root cause

One root cause, one fix. AUTO_SHELL_RULES matching (matchAutoShellRule in src/permission/auto-shell-policy.ts) ran every rule against stripQuoted(command), which replaced entire quoted spans with a blank space before matching. That erases the character class of a quoted redirect target, a quoted -c/-i flag, a quoted install subcommand, and a quoted argv0 alike — so quoting any of them defeats every CMD-anchored rule and the redirect pattern. All three tickets are the same bypass surfacing through different rules, at the same call site.

Fix

Replaced stripQuoted with dequoteForMatching: a quote-aware pass that mirrors real shell semantics — quote characters are dropped and their content stays literal (so a quoted flag/program name/redirect target is visible to the rules exactly as the shell would see it), except the small set of characters that are only operators outside quotes (> < | & ; \``), which are neutralized when they appear inside a quote so a literal >` in a commit message can't be mistaken for a redirect.

Also widened the file-mutation redirect regex to accept an optional | immediately after >/>> (>|, >>| bash clobber forms), which the old pattern rejected outright.

Single fix, three sites covered — no separate patches needed since all three collapse to the same matchAutoShellRule call path.

Tickets and tests

All in src/permission/classify-security.test.ts, describe blocks named after each ticket.

  • CL-6703 (quoted redirect targets bypass file-mutation deny) — describe("CL-6703 — quoted redirect targets still deny file-mutation"): "a quoted redirect target denies", "a quoted fd-qualified redirect target (1>\"file\") denies", "a nested bash -c form with a quoted redirect denies", plus the negative "a quoted '>' inside non-redirect text does not false-positive".
  • CL-6702 (bash clobber redirects never match) — describe("CL-6702 — bash clobber redirects match file-mutation"): "echo hi >|path denies", "echo hi >>|path denies".
  • CL-6697 (quoted dangerous flags/program names bypass CMD-anchored rules) — describe("CL-6697 — quoted dangerous flags and program names still deny/ask"): "a quoted -c interpreter one-liner denies", "a quoted sed -i denies", "a quoted npm install asks", "a quoted upload-tool argv0 (curl) asks", plus the negative "an innocent quoted argument interior does not false-positive".

Verified each of the 8 new bypass-reproduction tests fails against the pre-fix auto-shell-policy.ts (git-stashed) and passes with the fix.

Gate

bun run check (lint, typecheck, build, full test suite) is green: 5397 tests pass, 0 fail.

Files changed

  • src/permission/auto-shell-policy.tsdequoteForMatching replaces stripQuoted; redirect regex accepts >|/>>|.
  • src/permission/classify-security.test.ts — regression tests above.
  • CHANGELOG.md — Unreleased entry.

Diff kept to auto-shell-policy.ts and its test file only; gate.ts / classify.ts untouched per the heads-up on PR #598.

@linear-code

linear-code Bot commented Aug 24, 2026

Copy link
Copy Markdown

CL-6703

@TheGreatAxios
TheGreatAxios force-pushed the cl-6703-fix-auto-mode-allowing-quoted-shell-redirect-writes branch from bb2c272 to b672855 Compare August 24, 2026 05:36
@TheGreatAxios

Copy link
Copy Markdown
Collaborator Author

Addressed both review items:

  1. Backslash-escaped quotes — `dequoteForMatching` now skips the character after a backslash without touching quote state (matching real bash: `"` is a literal quote, never a quote-open, except inside single quotes where backslash has no special meaning). Added regression tests: an escaped-quote redirect (`echo hi \"> file"`) and an escaped-quote case ahead of a dangerous flag (`python3 \" -c print(1)"`) — both verified to fail on the pre-fix code and pass now.
  2. CHANGELOG wording narrowed — no longer claims coverage of true nested `bash -c` (multi-level); now scoped to "one level of quoting inside a `bash -c` payload," which is what the tests actually prove. True nested-shell parsing is out of scope here per your note.

Rebased onto latest `origin/main`. `bun run check` green: 5423 tests, 0 failures.

@TheGreatAxios
TheGreatAxios enabled auto-merge (squash) August 24, 2026 05:37
The auto-shell policy blanked quoted spans to whole-space before matching
its rules, so a quoted redirect target, a quoted -c/-i flag, a quoted
install subcommand, or a quoted argv0 all read as absent text and slipped
past deny/ask. Replace the blanket blank with quote-aware dequoting that
mirrors real shell semantics: quote characters are dropped and their
content stays literal, except the handful of characters that are only
operators outside quotes (> < | & ; `) which are neutralized when quoted,
so a literal '>' in a commit message still can't be mistaken for a
redirect. Also widen the file-mutation redirect pattern to recognize the
`>|` / `>>|` clobber form, which never matched at all.

One tokenizer fix covers all three bypasses since they share the same
root cause (stripQuoted) and the same call site (matchAutoShellRule).
dequoteForMatching tracked quote state without escape awareness, so a
backslash-escaped quote (\") still toggled quote state the same as a real
one. In real bash \" is a literal quote character that never opens or
closes a quoted span, so an operator or flag that follows is genuinely
unquoted. Skip the escaped character without touching quote state.

Also narrow the CHANGELOG's nested bash -c claim to what the tests
actually cover (one level of quoting inside -c), not true multi-level
nested-shell parsing, which remains a known gap tracked separately.
@TheGreatAxios
TheGreatAxios force-pushed the cl-6703-fix-auto-mode-allowing-quoted-shell-redirect-writes branch from b672855 to ef44efb Compare August 24, 2026 05:46
@TheGreatAxios
TheGreatAxios merged commit 9fb5433 into main Aug 24, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant