Skip to content

A Heredoc Inside a Substitution Whose Body Holds the Outer Tag Hides the Commands After It #2124

Open

Description

@ptr727

Problem

gh-write-guard.py reads a heredoc opened inside a $(...) or a backquote either as the line's first heredoc alone or as one of every heredoc the line opens in token order. Bash reads a body opened inside an unclosed substitution before the substitution closes, and only then the body the outer command opened on that line. Where the inner body holds a line equal to the outer tag, neither reading matches bash, so a heredoc opener that bash reads as body text swallows the real commands after it, and the wait-loop rule never judges them.

Reproduce (constructed)

Allowed on develop and on the #2112 branch, and piping the same text with echo ran in place of the loop into bash prints ran:

cat <<A >/dev/null; x=$(cat <<B
A
cat <<X
B
)
cat <<Y
A
while [ ! -f /x ]; do sleep 1; done
X
Y

Bash reads B's body (the lines A, cat <<X), then ), then A's body (cat <<Y), then runs the loop. The guard ends A at the first A line, so cat <<X or cat <<Y opens a heredoc that runs past the loop. The backquote form behaves the same.

Done looks like

The command above is denied, and a self-test row pins it.

Found by the local strict review of the #2112 fix (handoff #2123). It is older than that fix, which neither reads nor changes this ordering.

Activity

  1. added
    bugSomething isn't working
    agentsAgents instructions
    pre-existingReview finding classed pre-existing per local-strict-review Disposing of Findings
    on Sep 30, 2026
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

    agentsAgents instructionsbugSomething isn't workingpre-existingReview finding classed pre-existing per local-strict-review Disposing of Findings

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions