Development record
A shell or eval payload written as a here-document substitution is not read, though its text is the payload verbatim. sh -c "$(cat <<EOF … EOF)" and eval "$(cat <<'EOF' … EOF)" carry the document's text as the string the shell runs, but the tokenizer leaves a substitution's output unknown, so the payload is uninspectable and the family's loud WARN is the verdict: a blocked command in the document runs (review5-guard finding 3). Where the output is fixed — cat with nothing but the here-document, a quoted delimiter or a body with no expansion in it — the document's text can be read as the payload as well as the unknown output.
A shell or eval payload written as a here-document substitution is not read, though its text is the payload verbatim. sh -c "$(cat <<EOF … EOF)" and eval "$(cat <<'EOF' … EOF)" carry the document's text as the string the shell runs, but the tokenizer leaves a substitution's output unknown, so the payload is uninspectable and the family's loud WARN is the verdict: a blocked command in the document runs (review5-guard finding 3). Where the output is fixed — cat with nothing but the here-document, a quoted delimiter or a body with no expansion in it — the document's text can be read as the payload as well as the unknown output.
Grounds
- pursued: a blocked command in the document of sh -c or eval blocks under its own entry, while a clean document keeps its warn and the same document where no shell runs it allows; it would be shown wrong by a literal-document payload whose hazard allows, or by an expanding body read as literal
Frontmatter
| id | iss-2609252214215409 |
|---|---|
| type | issue |
| lifecycle | resolved |
| severity | minor |
.abcd/work/issues/resolved/iss-2609252214215409-a-shell-or-eval-payload-written-as-a.md
open on GitHub ↗ · commit history ↗
mentions1
- dcn-26092500000000172026-09-25 — Correction to the round-4 entry above on the shell guard's here-document bodies, with three further rulings (fix round 5 of lane guard, run A, closing review5-guard). Ruling (b) of that entry read an unquoted body line by line, and the round's report held that bash can only end such a body later than the guard, so the guard over-reads and never under-reads. That is false: in a body whose delimiter is unquoted, bash joins a physical line ending in an odd number of backslashes with the next line before it compares the delimiter, so `x\` followed by `EOF` does not end the body, and ending it there read the rest as command text, where a single-quoted span or a `#` hid a substitution the body runs (iss-2609252214137586). A later end read with a different grammar is an under-read. The body is now read by the logical lines bash compares: joined across an odd trailing run of backslashes, for an unquoted delimiter only; an even run and a quoted delimiter join nothing, and a `<<-` body strips the leading tabs of the joined line alone. (a) Inside double quotes a `${…}` ends at its own `}`, found as bash's parser finds it: a `"` in it opens a nested string, a `'` pairs with the next `'` for the parse only (the substitutions between them still run, and are followed), a bare `{` opens nothing. `echo "${MSG:-"don't"}"` and its kin, which blocked as `command-unparsable` after round 4, run; a `${` that never closes leaves the string as the text it was, and BLOCK stays the answer for a line the tokenizer cannot split (iss-2609252214217550). (c) A word that is wholly `"$(cat <<DELIM … DELIM)"`, whose body the shell does not change (a quoted delimiter, or an unquoted one with no `$`, backtick or backslash in it), is ALSO read as the document's text wherever it is a payload (`sh -c`, `eval`, `su -c`, `env -S`), beside the unknown reading, which keeps every signal it raises: a clean document still warns as an uninspectable payload, and a hazard in the document blocks under its own entry. Replacing the unknown reading was weighed and not taken, because a `cat` redefined earlier in the same line would print something else, and an additive reading cannot weaken a verdict (iss-2609252214215409). (d) One more accepted over-block, named so it is not mistaken for a defect: a here-document whose delimiter is a substitution (`cat <<$(echo EOF)`) is not run to learn the delimiter, so no line ends the document and the line blocks as `heredoc-unterminated`, although bash runs it; writing the delimiter out is the way past.