Skill tool silently substitutes $N-style tokens in skill body from invocation args

Status Open
Maintainer reply None cached
Activity 1 comment · opened Sep 15, 2026

What happened: Invoked a skill (via the Skill tool) with args: "scan jons/ONS_0??.md and report which files have findings". The returned skill body text had two legitimate awk field references, $2 and $0, silently replaced with literal words from the args string: substr($2,3) became substr(and,3) — and is the whitespace-split word at 0-indexed position 2 in the args — and substr($0,5) became substr(scan,5) — scan is the word at position 0. Every other line of the same SKILL.md file was unchanged (verified against a direct file read moments earlier in the same session).

Repro:

  1. Write a SKILL.md whose body contains a code block using awk with $0/$1/$2 etc. field references (e.g. awk '/pat/ {f=substr($2,3)}').
  2. Invoke the skill with an args string whose whitespace-split words happen to occupy the same 0-indexed positions as the $N tokens in the body.
  3. The skill body returned to the model has those $N substrings replaced with the corresponding word from args.

Suspected cause: The skill-loading/templating step appears to treat any $N substring in the skill body as a positional-parameter placeholder to be filled from the whitespace-split invocation args, without checking whether the surrounding context (e.g. an awk script) intends $N to mean something else entirely.

Impact: Beyond corrupting displayed documentation/examples, this is a content-integrity issue and a potential injection vector — if a skill body's $N pattern gets substituted with args text that later gets executed or trusted, that's a real problem, not just a cosmetic one.

Evidence: Affected skill file: .claude/skills/restore-headings/SKILL.md, "Auditing a fix" section, awk snippet (git diff <before> -- jons/ | awk '/^\+\+\+ b\// {f=substr($2,3)} ...').

View original on GitHub ↗

This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗