gh --body with backticks runs them as command substitution: PR comments post successfully with content silently deleted nf-hdxa ← Beads

closed priority 2 task unassigned

Twinned from https://github.com/cfsh/ninefold/issues/677 by tools/beads/import_github.py's reconcile pass.

Filed unclaimed from a strategic-uplift window. First-hand: I corrupted a PR comment this way today and only caught it by accident.

What happens

Every session writes PR comments and issue bodies full of backticked code — that is the house style, and the reviewer's ask ledgers depend on it. Written the obvious way:

```bash gh pr comment 654 --body "the R sub-floor item is now fixed" ```

bash treats the backticks as command substitution, runs R, and substitutes its output. The comment posts *successfully*, with the term silently deleted:

> "b7b87f9 takes the   sub-floor item further than *not reachable*"

The only signal was one line of unrelated-looking noise in the tool output:

``` /bin/bash: line 29: R: command not found ```

gh exits 0. The comment URL is returned. Nothing indicates the content is wrong.

Why it is worth more than "escape your backticks"
The fix, which is one rule

Always --body-file, never --body, for anything longer than a few words — write the text with the file tool, then:

```bash gh pr comment <n> --body-file <scratchpad>/reply.md gh issue comment <n> --body-file <scratchpad>/reply.md gh issue create --body-file <scratchpad>/issue.md ```

No shell parsing of the content at all. It also composes with #657's gh api -F body=@file workaround, which already requires a file.

Heredocs (<<'MDEOF', quoted delimiter) are equally safe and avoid the temp file; the unquoted form (<<MDEOF) is not — it interpolates the same way.

Where it should live
Not hypothetical

Two instances in one session, both mine:

  1. gh pr comment --body "… R …" → term deleted from a posted comment; repaired via gh api -X PATCH repos/…/issues/comments/<id> -F body=@file after noticing the command not found line.
  2. Same session, a gh issue comment with ` pgrep -c -f rebuild_f5.py inside a double-quoted --body` — that one happened to be harmless because the substitution produced a number, which is arguably worse: it posted something plausible.

Refs #657 (same "the tool reports success and the thing did not happen" shape, different cause).

Dependencies

None.

Comments

No comments.

Add a comment