You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This was generated by AI during a session in github-iac, where the defect was hit live.
Defect
The typos-format PostToolUse hook silently rewrote an abbreviated git SHA in a file I had just
written, corrupting it. 534caf5 became 534calf5 — caf "corrected" to calf.
I only caught it because I re-read the file. The hook reports its rewrite as "likely a formatter"
via the PostToolUse notice, which does not say what changed, so an agent that writes and moves on
ships the corruption. That is the actual severity here: silent data corruption in agent-authored
files, not a cosmetic annoyance.
Reproduction — minimal and verified
typos-cli 1.44.0, on this file:
short `534caf5`
long `534caf5d6ebab90faf8c1932c5d8007cba3710b9`
bare 534caf5
other short sha `1a2caf9`
error: `caf` should be `calf` typotest.md:1:11 (inside backticks)
error: `caf` should be `calf` typotest.md:3:9 (bare)
error: `caf` should be `calf` typotest.md:4:21 (different SHA, also inside backticks)
Two findings worth separating:
Backticks are not respected. Two of the three hits are inside inline code spans. A code span
is the canonical way to mark "this is a literal, do not language-process it", and the hook writes
through it anyway. Any identifier, hash, hex color, or flag inside backticks is exposed.
The 40-character SHA is NOT flagged — only the 7-character abbreviated form. typos has a
heuristic that skips long hex strings and recognizes them as hashes; a 7-char abbreviated SHA is
below that threshold and gets word-split instead. So the corruption specifically targets the short SHA form, which is exactly the form used in prose, changelogs, handoffs, ADRs, and commit
references.
It is not limited to caf. Any abbreviated SHA whose hex happens to contain a token in the typos
dictionary is a candidate — 1a2caf9 above is a second example, and the dictionary is large.
Why the existing config gate does not cover this
#884 established that the hook must not be a no-op on zero-config repos. Correct — but the
consequence is that it now runs with stock typos defaults on repositories that never opted in and
have no _typos.toml to add an extend-ignore-re. github-iac is exactly that case. So the
population most exposed to this is the one with no mechanism to defend against it.
Suggested direction (not a decision — the maintainer's call)
Options, roughly in increasing order of effort:
Ship a baseline extend-ignore-re with the hook covering abbreviated git SHAs
(\b[0-9a-f]{7,40}\b) and inline code spans, so zero-config repos inherit a safe floor rather
than stock defaults.
Make the PostToolUse notice name the rewrite — a diff, or at minimum the corrections applied.
Worth doing regardless of which of the above is chosen: a silent rewrite an agent cannot see is
the part that turns a false positive into shipped corruption.
Acceptance
An abbreviated git SHA survives the hook unchanged, in prose and inside backticks
Zero-config repositories do not get destructive stock-default autocorrection, or the floor they
get is explicitly chosen rather than inherited
When the hook rewrites a file, what it changed is visible to the caller
This was generated by AI during a session in
github-iac, where the defect was hit live.Defect
The
typos-formatPostToolUse hook silently rewrote an abbreviated git SHA in a file I had justwritten, corrupting it.
534caf5became534calf5—caf"corrected" tocalf.I only caught it because I re-read the file. The hook reports its rewrite as "likely a formatter"
via the PostToolUse notice, which does not say what changed, so an agent that writes and moves on
ships the corruption. That is the actual severity here: silent data corruption in agent-authored
files, not a cosmetic annoyance.
Reproduction — minimal and verified
typos-cli 1.44.0, on this file:Two findings worth separating:
is the canonical way to mark "this is a literal, do not language-process it", and the hook writes
through it anyway. Any identifier, hash, hex color, or flag inside backticks is exposed.
typoshas aheuristic that skips long hex strings and recognizes them as hashes; a 7-char abbreviated SHA is
below that threshold and gets word-split instead. So the corruption specifically targets the
short SHA form, which is exactly the form used in prose, changelogs, handoffs, ADRs, and commit
references.
It is not limited to
caf. Any abbreviated SHA whose hex happens to contain a token in the typosdictionary is a candidate —
1a2caf9above is a second example, and the dictionary is large.Why the existing config gate does not cover this
#884established that the hook must not be a no-op on zero-config repos. Correct — but theconsequence is that it now runs with stock typos defaults on repositories that never opted in and
have no
_typos.tomlto add anextend-ignore-re.github-iacis exactly that case. So thepopulation most exposed to this is the one with no mechanism to defend against it.
Suggested direction (not a decision — the maintainer's call)
Options, roughly in increasing order of effort:
extend-ignore-rewith the hook covering abbreviated git SHAs(
\b[0-9a-f]{7,40}\b) and inline code spans, so zero-config repos inherit a safe floor ratherthan stock defaults.
config. Preserves typos-format: opt-in config-gate makes the hook a silent no-op on zero-config repos, defeating the plugin's own auto-fix purpose #884's intent (not a silent no-op — it still surfaces findings) without
write-through on repos that never asked for it.
Worth doing regardless of which of the above is chosen: a silent rewrite an agent cannot see is
the part that turns a false positive into shipped corruption.
Acceptance
get is explicitly chosen rather than inherited
Related