GNU patch doesn’t separate real commit diffs from diff-shaped text embedded in commit messages, letting a crafted .patch file write arbitrary files.
Key Takeaways
GitHub’s .patch URLs export mail-style patches that concatenate the commit message and the real diff with no structural boundary between them.
A commit message containing a valid unified diff block will be applied by patch -p1 as if it were real – the demo creates SHOULD_NOT_BE_HERE.md from a commit that never touched it.
The wget + patch workflow is old and common, not exotic – anyone piping GitHub .patch URLs through GNU patch is exposed.
GNU patch accepted a diff targeting .git/hooks/post-applypatch locally; git apply and git am blocked the .git/ path but still applied injected diffs to ordinary working-tree files.
The bug’s ownership is unresolved: GNU patch, GitHub’s export format, or the underlying patch-format contract are all plausible owners.
Hacker News Comment Review
Commenters note this is a recurring class of problem with Unix tool formats: in-band signaling with no escaping means confusion is structurally guaranteed, not an edge case.
A targeted fix proposed: GitHub could return patches formatted like git show, with commit message lines indented, giving GNU patch a clear structural separator – though git format-patch doesn’t do this either.
Notable Comments
@Groxx: “no escaping” framing – indenting commit message lines in the export would likely close the ambiguity without changing the format spec.