Skip to content

Security: heredoc opener can bypass command auto-approval via operator chaining #640

Description

@edelauna

Summary

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:

if (restoredLine.includes("\n")) {
    allCommands.push(restoredLine)
    continue
}

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:

return lowerPrefix === "*" || trimmedCommand.startsWith(lowerPrefix)

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.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions