A backtick in a comment made bash run the function it was naming

The fourth time this bug landed, it landed inside the comment explaining the third. A small program was embedded in a double-quoted shell string. Its comment named the function the previous fix had been about, and named it in backticks, the way you name code in prose. Inside a double-quoted shell string a backtick opens a command substitution. Bash tried to execute the function the comment was naming (build rules).

The earlier three were the same family. Twice in one file during one cycle, the second time again inside the comment explaining the first. Once more in a different lane. Each time the character was an apostrophe or a backtick, each time it sat in a program passed to a shell as a string, and each time the person writing it knew the rule.

Why a comment is the worst place for it

Inside a single-quoted shell string, one apostrophe closes the string and the shell reads the rest as its own syntax. Inside a double-quoted one, a backtick starts a command and a dollar sign starts an expansion. None of that is obscure. What makes it recur is where the characters come from.

Code is written carefully, and the fix for a quoting bug is usually correct. The comment beside the fix is written in English, by someone explaining what went wrong, and English is full of apostrophes. “Don’t”, “it’s”, the possessive on a function name, a backtick around an identifier because that is how identifiers look in prose. The explanation of the bug is the text most likely to contain the bug’s trigger, and it is the text nobody reads as code.

A coding workflow where AI agents write the comments makes this sharper, not softer. Agents write fluent, well-punctuated explanations by default, and they format identifiers with backticks without being asked.

The rule is about where the program lives

We stopped trying to write the embedded program more carefully. The rule now: a program embedded in a shell string carries no apostrophes and no single quotes, in code or in comments, and inside a double-quoted string the same holds for a backtick and a dollar sign. The moment the embedded program wants any of those characters, it moves into its own file (build rules).

That second sentence is the part that does the work. A rule that says “be careful with quotes” asks for attention at exactly the moment attention is on something else, which is how the comment explaining the first fix produced the second. A rule that says “this program is now a file” removes the shell from the path entirely. A file has no surrounding quotes to close.

The general shape

Any time one language is carried inside a string of another, the outer language reads the inner one’s characters first. Shell inside YAML, SQL inside a format string, JSON inside a shell argument, a regex inside a JSON value. Each layer has a few characters it treats as structure, and the inner text was written by someone thinking only about the inner layer.

The cheap fix is escaping. The durable fix is to stop nesting: put the inner program in a file, pass paths and arguments rather than source, and let each language be parsed by exactly one reader.

What we would tell you to check

Search your scripts and CI configuration for programs passed inline to an interpreter: node -e, python -c, bash -c, a heredoc fed to anything. Read the comments inside them as code. If a comment contains an apostrophe, a backtick or a dollar sign, it is one edit away from changing what the outer shell runs, and the edit most likely to add one is the next person explaining a bug.