Commits on Oct 26, 2026
guardrail: a heredoc body is data, not commands, unless a shell reads it
The engine split a Bash command on newlines and judged every line as a command, so a file written with `cat > f <<'EOF'` had each body line scanned: a line beginning with `at` asked about the `at` scheduler. It stopped three unattended paddock builds in a week (2026-10-25/26).
strip_heredocs() drops each heredoc body (and its closing word) before the split. The opening line stays, so the command itself is still judged. Quoting of the delimiter, `<<-` with tabbed closers, several heredocs on one line, unterminated bodies, quoted `<<` and `<<<` here-strings are handled. A body read by a shell (bash, sh, zsh, dash, ksh, ssh, eval, su, with wrappers and paths stripped) is kept: those lines run, and `rm -rf /` inside `bash <<EOF` or `ssh host bash -s <<EOF` is still denied.
Tests: 23 new cases, plus two over stdin under the system interpreter.…