[BUG] Heredoc as first argument bypasses pipe target permission checks

Status Fixed / completed
Maintainer reply ✓ Yes — ashwin-ant
Activity 5 comments · opened Apr 15, 2026 · closed Apr 18, 2026
💡 Likely answer: A maintainer (ashwin-ant, collaborator) responded on this thread — see the highlighted reply below.

Bug

When a heredoc marker (<<EOF or <<'EOF') is the first token after the command name, the permission system fails to evaluate pipe targets. An ask-listed command silently auto-allows when it appears after |.

Reproduction

Given these permission rules:

{
  "permissions": {
    "allow": ["Bash(cat:*)", "Bash(sort:*)", "Bash(head:*)"],
    "ask": ["Bash(some-script:*)"]
  }
}

Prompted (correct behavior)

echo test | some-script              # pipe target evaluated
cat /dev/null | some-script          # pipe target evaluated
cat --number <<'EOF' | some-script   # args before heredoc — pipe target evaluated
head -1 <<'EOF' | some-script        # args before heredoc — pipe target evaluated
sort --reverse <<'EOF' | some-script # args before heredoc — pipe target evaluated

Auto-allowed (bug — ask rule on pipe target skipped)

cat <<'EOF' | some-script            # heredoc is first arg — pipe target NOT evaluated
sort <<'EOF' | some-script           # heredoc is first arg — pipe target NOT evaluated
head <<'EOF' | some-script           # heredoc is first arg — pipe target NOT evaluated

Both quoted (<<'EOF') and unquoted (<<EOF) heredoc delimiters trigger the bug.

Expected behavior

The pipe target should be evaluated against permission rules regardless of whether the source command uses a heredoc.

Likely cause

The permission parser appears to stop analyzing the command at << when it is the first argument, treating everything after it (including | some-script) as heredoc content rather than continuing to parse the pipeline.

Impact

Any ask- or deny-listed command can be silently auto-allowed by piping from an allow-listed command with an immediate heredoc. This is a permission bypass — the user configured ask specifically to be prompted before execution, but never sees the prompt.

Related issues

  • #42426 — heredoc bypassing git commit permission checks (closed, same class)
  • #47752 — "Unhandled node type: pipeline" in permission prompt
  • #11932 — auto-approve patterns not matching heredoc commands
  • #30519 — meta-issue on permission matching

Environment

  • Claude Code on Linux (WSL2 Ubuntu 24.04)
  • Permissions configured in managed-settings.json (system-level)

View original on GitHub ↗

5 Comments

github-actions[bot] · 6 months ago

Found 3 possible duplicate issues:

  1. https://github.com/anthropics/claude-code/issues/42426
  2. https://github.com/anthropics/claude-code/issues/47752
  3. https://github.com/anthropics/claude-code/issues/25825

This issue will be automatically closed as a duplicate in 3 days.

  • If your issue is a duplicate, please close it and 👍 the existing issue instead
  • To prevent auto-closure, add a comment or 👎 this comment

🤖 Generated with Claude Code

spawnia · 6 months ago

Not a duplicate of any of the three suggested issues:

  • #42426 — heredoc bypassing git commit permission checks. That bug is about the source command's own rule being bypassed. My issue is about the pipe target's ask rule being skipped.
  • #47752 — "Unhandled node type: pipeline" error in the permission prompt UI. A parser error, not a silent permission bypass.
  • #25825 — heredoc-containing commands being split into multiple permission entries in settings.local.json. A storage/serialization bug.

This issue is about a specific, empirically verified condition: when <<EOF is the first argument after an allow-listed command, the permission parser fails to evaluate the pipe target against ask/deny rules. The pipe target silently auto-allows. Adding any argument before the heredoc marker restores correct behavior. See the reproduction table in the issue description.

ashwin-ant collaborator · 6 months ago

This was fixed in v2.1.73 — Heredocs used as the first argument to a piped command are now treated as too complex to auto-allow, closing a permission-check bypass. If you're still seeing this in the latest version, please comment with your version and repro and we'll reopen.

spawnia · 5 months ago

Still reproducing on v2.1.104 (Linux, WSL2 Ubuntu 24.04).

Permissions

{
  "allow": ["Bash(cat:*)", "Bash(sort:*)", "Bash(head:*)", "Bash(echo:*)"],
  "ask": ["Bash(pandoc:*)"]
}

Prompted (correct)

echo test | pandoc --to=plain            # pipe target evaluated ✓
cat --number <<'EOF' | pandoc --to=plain  # args before heredoc ✓

Auto-allowed (bug — ask rule on pipe target skipped)

cat <<'EOF' | pandoc --to=plain    # heredoc first arg ✗
sort <<'EOF' | pandoc --to=plain   # heredoc first arg ✗
head <<'EOF' | pandoc --to=plain   # heredoc first arg ✗
cat <<EOF | pandoc --to=plain      # unquoted heredoc ✗

Both quoted (<<'EOF') and unquoted (<<EOF) heredocs trigger the bypass. Adding any argument before the heredoc marker makes the pipe target evaluate correctly.

Why v2.1.73 didn't fix this

The v2.1.73 changelog entry is:

Fixed freezes and 100% CPU loops triggered by permission prompts for complex bash commands

This fixed the crash symptom (CPU loops on complex commands) but not the permission bypass. Before v2.1.73, these heredoc-first-arg pipes caused freezes; after v2.1.73, they silently auto-allow instead of prompting. The tree-sitter AST walker still doesn't evaluate the pipe target when a heredoc is the first argument — it just no longer crashes trying.

This is the same root cause as #47752 ("Unhandled node type: pipeline"), where the AST walker's pipeline handling breaks down in specific heredoc nesting contexts.

github-actions[bot] · 5 months ago

This issue has been automatically locked since it was closed and has not had any activity for 7 days. If you're experiencing a similar issue, please file a new issue and reference this one if it's relevant.