← Back to Blog

What Git 3.0's SHA-256 Migration Gets Wrong About Real Attacks

Git 3.0 is switching its default content hash from SHA-1 to SHA-256. In Git 3.0’s upcoming SHA-256 default will be a costly mistake, GitHub co-founder Scott Chacon argues the change will cost the industry years of broken tooling to defend against a threat that barely resembles how real attacks on source code actually happen.

Table of Contents

What Chacon’s post argues

Scott Chacon, a co-founder of both GitHub and GitButler and the author of Pro Git, wrote the post as a direct response to an upcoming Git 3.0 breaking change: the default object hash moves from SHA-1 to SHA-256. His argument isn’t that SHA-256 is a bad hash. It’s that the industry is about to absorb an enormous migration cost, broken CI pipelines, forges that don’t support the new format, years of tooling churn, to defend against an attack vector he calls “maybe the dumbest possible way to get untrusted code on a system” next to how real supply-chain attacks happen.

His central claim is that trust in Git was never rooted in the hash function. It comes from where you pull code from, an idea he traces back to Linus Torvalds at the project’s founding two decades ago. Real attackers don’t rent GPU farms to engineer a hash collision, Chacon argues; they socially engineer their way into maintaining an already-trusted package, or simply pay off a tired open source maintainer.

Why SHA-1 counts as “broken,” and why that word is doing a lot of work

Cryptographers call SHA-1 broken because of two published results, SHAttered in 2017 and SHA-1 is a Shambles in 2020, that showed how to manufacture two different files sharing the same hash, for a cost Chacon estimates at a few tens of thousands of dollars in GPU time. But Chacon draws a sharp line between that kind of engineered “collision attack” and a “second-preimage attack,” where an attacker has to produce a malicious replacement for a file someone already trusts and has already pulled. He argues second-preimage attacks against SHA-1 remain effectively impossible, and that most of what people worry about actually requires one.

Chacon also puts a number on how unlikely an accidental collision is: SHA-1’s 160-bit output would need roughly 1.4 septillion random files in a single project before two of them accidentally matched, which he says is why, across twenty years and billions of commits, nobody has ever recorded one.

The pushback: “theoretical” undersells what’s already been demonstrated

Not everyone in the discussion accepted that framing. Commenter kpcyrd argued the post undersells how practical SHAttered already was: it was “specifically a practical proof of concept” in 2017, not a theoretical result, and Git projects escaped unaffected mainly because nobody bothered brute-forcing a Git-blob-shaped prefix, not because Git’s design was immune. kpcyrd also challenged Chacon’s split between collision and second-preimage attacks, pointing out that a plain collision attack is already enough to smuggle malicious code once two repositories land on the same commit hash, a realistic scenario when CI pipelines compare commits across forks.

Chacon replied under his own account and stood by the “impractical to exploit” framing while agreeing the underlying papers are real. Commenter mistercow added a technical wrinkle: the Shambles result is specifically a chosen-prefix collision, sitting between Chacon’s two categories rather than cleanly inside either one, a distinction Chacon acknowledged was fair.

The migration cost is not hypothetical

Whatever you make of the threat model, the cost side of Chacon’s argument held up well in the discussion. Commenter TheCondor described trying SHA-256 repositories about eighteen months before this conversation and finding that CI runners and action tooling broke outright, badly enough that they abandoned the experiment and rebuilt their repos under SHA-1. Commenter plorkyeran confirmed that GitHub itself doesn’t support SHA-256 repositories outside a closed beta, and several commenters agreed that mixing SHA-1 and SHA-256 objects inside Git submodules has no settled solution yet. A popular hosting platform without public support, plus a genuinely unresolved submodule problem, is the concrete version of the “costly mistake” in Chacon’s title.

The rebuttal: it might be a smoother migration than it sounds

Other developers pushed back on the “train wreck” framing using Git’s own documentation. Commenter GrantMoyer pointed to Git’s official hash-function-transition docs, which state that SHA-1 repositories keep working untouched, only new repositories default to SHA-256, and the two hash representations are designed to map one to one. Replying to that, commenter froh called it “a perfect and user friendly migration strategy” and asked what problem actually remained if existing SHA-1 workflows are left alone.

A third thread in the discussion, raised by commenter 0x00cl, suggested the real driver behind the change isn’t a live exploit at all: SHA-1 is explicitly disallowed under compliance standards like FIPS 140-2 at some organizations, independent of whether anyone has used it to attack them. If that’s accurate, procurement and certification requirements may be doing as much work here as the cryptography.

What I’d check before adopting any “security upgrade”

None of this makes SHA-256 a bad choice, or means Git’s maintainers are wrong to eventually move off SHA-1. My take is narrower: before adopting a breaking “security upgrade” in your own stack, map the actual attack path first, not the scariest-sounding cryptographic property attached to it. Ask who would realistically attack you, what they’d actually have to do to pull it off, and whether the change you’re about to ship addresses that path or a different, more theoretical one.

If your organization has to drop SHA-1 for compliance reasons, that’s a real reason to migrate, so say that plainly instead of dressing it up as stopping an active threat. And if you’re deciding whether to flip Git 3.0’s new default on your own repos, read the thread first. The counterpoints about GitHub’s beta-only support and the submodule gap are exactly the kind of detail that turns a one-line config change into a week of debugging broken pipelines.

FAQ

Is SHA-1 actually broken in Git?

Mathematically, yes. Published research, SHAttered in 2017 and SHA-1 is a Shambles in 2020, shows researchers can manufacture two files sharing the same SHA-1 hash for a cost Scott Chacon estimates in the tens of thousands of dollars. But nobody has used that technique to insert malicious code into a real Git project, and accidental collisions remain effectively impossible at Git’s scale.

Should I switch my own repositories to SHA-256 right now?

Not without checking your tooling first. Commenters in the discussion found that GitHub doesn’t yet support SHA-256 repositories outside a closed beta, that CI runners and actions broke for early adopters who tried it, and that mixing SHA-1 and SHA-256 objects inside submodules has no clean solution yet. Existing SHA-1 repositories keep working as-is after Git 3.0 ships; only new repositories get the new default.

What’s actually driving Git’s move to SHA-256, if not a known exploit?

One commenter in the discussion pointed out that SHA-1 is explicitly disallowed under compliance frameworks like FIPS 140-2 at some organizations, independent of any demonstrated attack. That compliance pressure, rather than a documented real-world breach, may be as large a driver as the underlying cryptography.

Sources