You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Security: heredoc opener can bypass command auto-approval via operator chaining #640
A command like cat <<EOF && rm -rf /tmp\nhello\nEOF with an allowlist of ["cat"] is auto-approved, allowing arbitrary operators chained on the heredoc opener line to execute without user approval.
Root cause
In src/shared/parse-command.ts:519-525, when a top-level quote placeholder is restored and the resulting string contains embedded newlines (i.e. a heredoc span), the entire restored string is pushed as a single atomic command:
This means cat <<EOF && rm -rf /tmp\nhello\nEOF is treated as one command. In src/core/auto-approval/commands.ts:145-148, that single command is validated by prefix match:
Since the string starts with cat, it matches the "cat" allowlist entry and is auto-approved — including the && rm -rf /tmp operator chain that follows the heredoc opener.
Fix
Split and validate operators on the heredoc opener line before treating the body as opaque. Only the heredoc body content (lines between the opener and the terminator) should be atomic. The opener line itself (cat <<EOF && rm -rf /tmp) should be split on &&, ||, ;, and | operators and each sub-command validated independently.
Add a regression test: cat <<EOF && rm -rf /tmp\nhello\nEOF with allowlist ["cat"] should not return auto_approve.
Discovered
Identified during code review of PR #250 (chore: re-enable prefer-const ESLint rule). The vulnerability is pre-existing and unrelated to that PR.
This bug still occurs on main (18861b2) and after #2397.
Command
Allowlist
Denylist
parseCommand result
Decision
cat <<EOF && rm -rf x + body + EOF
cat
rm
1 command (the full text)
auto_approve
cat <<EOF; rm -rf x + body + EOF
cat
rm
1 command (the full text)
malformed_command
cat <<EOF + body + EOF + rm -rf x on the next line
cat
rm
cat <<EOF…EOF, rm -rf x
auto_deny
The root cause in this issue is now in a different location. #2397 changes the multi-line branch of parseCommand: it splits the line with parseCommandLine before it restores the quotes. But the heredoc scanner in scanTopLevelQuotes masks the text from <<EOF to the terminator, which includes && rm -rf x on the opener line. So that text is inside one placeholder, and no split occurs.
A possible fix: when the scanner finds a heredoc opener, mask only the body and the terminator line, not the rest of the opener line. Then parseCommandLine splits the opener line on &&, ||, ; and |.
I can work on this after #2397 if a maintainer assigns it to me.
Activity
kanchinadd98 commentedon Nov 10, 2026
This bug still occurs on
main(18861b2) and after #2397.parseCommandresultcat <<EOF && rm -rf x+ body +EOFcatrmauto_approvecat <<EOF; rm -rf x+ body +EOFcatrmmalformed_commandcat <<EOF+ body +EOF+rm -rf xon the next linecatrmcat <<EOF…EOF,rm -rf xauto_denyThe root cause in this issue is now in a different location. #2397 changes the multi-line branch of
parseCommand: it splits the line withparseCommandLinebefore it restores the quotes. But the heredoc scanner inscanTopLevelQuotesmasks the text from<<EOFto the terminator, which includes&& rm -rf xon the opener line. So that text is inside one placeholder, and no split occurs.A possible fix: when the scanner finds a heredoc opener, mask only the body and the terminator line, not the rest of the opener line. Then
parseCommandLinesplits the opener line on&&,||,;and|.I can work on this after #2397 if a maintainer assigns it to me.