Git Signed Hash Malleability
Abstract
Git commit signing is widely entrusted to serve as evidence that a commit hash uniquely and immutably identifies a specific piece of signed content. We show this invariant does not hold. Given any signed commit, an attacker _without access to the signing key, and without breaking SHA2_ can produce a second, distinct commit with an identical tree, identical metadata, a valid signature, and a Verified badge from a Git Forge such as Github, differing only in its commit hash. The modified commit cascades to modify the values of all the subsequent, dependent commit hashes, hence we introduce the terminology hash chain malleability to describe this phenomenon. The malleability in signed Git hashes is feasible due to the inherent malleability present in many of the data representations that make up a commit. In this paper we show three such malleation routes: (i) algebraic inversion __ __ __ for ECDSA; (ii) structural insertion of an unhashed OpenPGP subpacket (RFC 4880 5.2.3) for RSA and EdDSA; and (iii) non-canonical DER length re-encoding (X.690 10.1) inside the CMS envelope for S/MIME. Algebraic inversion for ECDSA signatures and subpacket insertion were found to pass local verification ( `git verify-commit` ), and all three methods yield a persistent, independent Verified record on Github. We discuss the consequences of Git hash chain malleation for hash-based commit blocking, dependency pinning (Nixpkgs, Go modules, Github Actions), and reproducible-build systems that treat the commit hash as a content-addressable primary key, and we provide proof-of-concept tooling that automates all three routes.