Skip to content
feed: live
>_0dayNews
supply chain
Analysis

Git Hash Chain Malleability: The Supply Chain Risk

SHA-1 is still the default in most Git repositories. Here is what hash chain malleability means, what it puts at risk, and how to close the gap.

Git Hash Chain Malleability: The Supply Chain Risk
Image: AI-generated — no human photographer / 0dayNews AI Cover · Generated on-site infrastructure — no external license
fuseMarisol "Fuse" Delgado·Published ·3 min read

Most Git repositories still rely on SHA-1 to identify every object they contain. Blobs, trees, commits, tags: each gets a 40-character SHA-1 hash. The assumption baked into this model is that two different objects will never produce the same hash. That assumption has been demonstrably wrong since 2017, and the supply chain exposure it creates has not gone away.

What hash chain malleability means

Git’s object model is a content-addressed store. Every commit points to a tree, every tree points to blobs or subtrees, and every parent reference is just a SHA-1. The chain of hashes is what makes git log --verify and reproducible builds possible: downstream consumers check the commit hash and trust that the content matches.

Malleability enters when that chain can be forged. If an attacker can produce two distinct git objects with the same SHA-1, they can substitute malicious content for the verified content without changing the identifier that auditing systems check. Package managers that pin to a git commit SHA, CI pipelines that fetch and hash-check, and dependency audits that log commit IDs: all of them trust the SHA-1 as proof of identity.

The SHAttered baseline

In February 2017, researchers at Google and CWI Amsterdam published a practical SHA-1 collision: two PDFs with identical SHA-1 hashes but different content, the SHAttered attack. The collision required roughly 2^63.1 SHA-1 compressions, which is within reach of a state actor or a well-resourced threat group.

Git’s response was to ship SHA-1DC (collision-detecting SHA-1), which detects the specific manipulation pattern needed to engineer a collision and rejects objects that trigger it. SHA-1DC is the default in Git 2.13 and later. If you are running a current version of Git or using any major hosted platform, your SHA-1 is SHA-1DC, not bare SHA-1. That matters: a direct replay of the SHAttered technique will not work against a patched deployment.

What SHA-1DC does not fix is the underlying weakness in SHA-1’s collision resistance. It blocks known attack patterns. A novel collision technique that avoids the detected structures could still succeed, and SHA-1 cryptanalysis continues to advance. The margin is shrinking.

The supply chain exposure

The highest-risk scenario is not an attacker who compromises your Git server directly. It is an attacker who controls a dependency, a mirror, or an intermediate build cache: a third-party package whose upstream repository is under attacker influence, or a forked repository with a crafted history that produces matching SHAs for some objects.

If your pipeline fetches dependencies by commit SHA without additional signature verification, a collision-crafted substitution can pass your hash check. The CrowdSec source code theft via TanStack and the JFrog Artifactory backdoor chain both show how supply chain compromises operate at the dependency layer, where CI systems trust the hash without verifying whether that trust is earned.

The attack is not theoretical. The computational cost to produce a targeted SHA-1 collision for a specific high-value git object is higher than a generic collision, but it falls each year. Waiting for a CVE ID before treating this as a risk is how teams end up doing emergency response.

What to actually do

SHA-256 migration is the long-term fix. Commit signing is the near-term defense layer. Neither is optional if your repository is part of a production supply chain.

Migrate to SHA-256 where you can. Git 2.29 introduced SHA-256 as a repository object format (git init --object-format=sha256). SHA-256 has no known practical collision attack and a much larger output space. Migration is not seamless: SHA-256 repos and SHA-1 repos cannot directly interoperate, so plan transitions around forks, submodules, and any tooling that parses raw object hashes. Start with new repositories and greenfield projects.

Sign commits and tags. git commit -S and git tag -s with a GPG or SSH key add a signature that is separate from the hash chain. A signature verifies the author’s identity independent of the SHA-1. Downstream consumers can run git verify-commit <hash> and git verify-tag <tag> before building. If your build pipeline does not check those signatures, add that step now.

Pin submodule references with signature checks. Pinning to a commit SHA is not enough. Pin to a signed tag or a commit SHA with a verified signature from a known key.

Audit your provenance tooling. SLSA (Supply-chain Levels for Software Artifacts) level 2 and above require build provenance attestations that go beyond a commit hash. Tools like cosign, Sigstore, and in-toto produce signed attestations at build time that do not depend on SHA-1 at all. Review which level your critical builds currently achieve.

No CVE has been assigned specifically to SHA-1’s weakness in Git’s object model; the migration is a proactive hardening effort, not a response to an active tracked exploit. That framing should not be confused with optional. Seven years after SHAttered, SHA-1 repositories that rely on the hash alone for integrity are running on borrowed time.

Patch this first: sign your tags, verify those signatures in CI, and scope your SHA-256 migration path. Then deprioritize the rest of the hardening backlog.

Found this useful? Share it.