The Verified seal trap: malleable signatures threaten the uniqueness of the hash in Git's commitments

Author: Published 5 min de lectura 128 reading

The images in this article were generated with artificial intelligence. How we publish

A new research work by Jacob Ginesin (PhD in Carnegie Mellon and cryptographic auditor in Cure53) disposes of an extended assumption: that a signed confirmation (commit) in Git is, in itself, a unique and immutable name for its content. The technique does not break SHA-1 or SHA-256 or alter the code; it takes advantage of the malleability of signatures- different and valid ways to represent the same signature - to rewrite the signature bytes that are included in the commit object, thus changing their hash without touching files, author or date. Ginesin documents three concrete vectors (ECDSA, RSA / EdDSA with unauthenticated OpenPGP fields and S / MIME with non-canonic DER encoding) and accompanies its study with test tools and demo repositories that show how GitHub continues to print the "Verified" seal after these mutations.

The root of the problem is not Git or the humans who sign, but how the forges consume and trust the signature: GitHub and other services do not normalize the signatures before they are verified and associate the Verified seal to the exact hash of the object received. This allows for practical operating scenarios: to block a commit by its hash leaves a hole - an attacker can repush the same confirmation with re- encoded signatures under a different hash and, yet, to see it marked as verified -; redoubling systems, block lists and source bitals that use only the hash will inherit the same fragility; a compromised mirror can return validly signed confirmations whose representation in bytes (and therefore its hash) differs from the version in the canonical forge.

The Verified seal trap: malleable signatures threaten the uniqueness of the hash in Git's commitments
Image generated with IA.

It is important to stress what this is not: it is not a door to change the content without the signature detecting it. The film content of blobs and trees remains identical, and pinching a complete hash to obtain code continues to ensure that you will receive exactly what hash corresponds to or fail to download. The issue is semantic and operational: the "Verified" seal does not guarantee that the hash is a unique and immutable name of the signed object And many tools trust that wrong guarantee.

The practical lesson recalls a well-known precedent in applied cryptography: Bitcoin stumbled upon a symmetry of ECDSA that allowed to change the value s by n − s and modify the transaction ID without the private key; the solution was to impose a canonical form ("low-S") and, in an architectural change, to separate signatures from the identification with SegWit. The equivalent recommendation for forges is obvious and technical: canonize the representation of the signatures before verifying and before registering a seal of trust. In practice that means accepting only canonical forms (e.g. low-S for ECDSA), removing or normalizing OpenPGP unauthenticated fields and validating / normalizing DER encoding in S / MIME.

What should each actor do? For forging (GitHub, GitLab, etc.) the action is clear and urgent: normalize the signatures before marking them as verified, store and recheck the canonized form and invalidate stamps if the signature or key is no longer canonical or are revoked. For tools that block by hash, deduplicate or compute traceability, the recommendation is not to trust the gross hash of an incoming signed object: verify the signature, canonize it and then compute the identifier they will use for lock or log, or alternatively base the deduplication on content tracks (tree / blobs) instead of the hash of the complete commit object.

For developers and consumers of packages or Actions the good news is that the best practices do not change root: continuing to paint complete commitments is correct, and anchorage also chemicals independent of the artifacts or use systems that verify content (e.g. fixed output derivations in Nix) adds a backup that avoids whole kinds of problems. However, there is an adjustment in surveillance: the "Verified" seal should not be used as the only safety criterion to accept or block code; that seal shows who signed, not that hash is a unique and unbribe identity.

The Verified seal trap: malleable signatures threaten the uniqueness of the hash in Git's commitments
Image generated with IA.

Ginesin's work was reported to relevant projects (Git, GNU and Forges) and, at least at the time of its publication, he still expected a spread patch. The community has mature conceptual arrangements: canonicalizing signatures is a well-known and well-understood practice. The first obvious point of attention is S / MIME, where the public tool reproduces cases that strict local git reject but that GitHub accepts as "Verified."

In short, we are faced with a problem of operational confidence, not content integrity: the forks must correct their verification pipeline so that the "Verified" band really means what users expect. In the meantime, security and supply infrastructure managers should update their locking and deduplication logic to validate and canonize signatures before relying on hash, and developers should continue to anchor units with complete hashes and, where possible, with additional checksums and reproducible device verification mechanisms.

To read the work and tests published by Ginesin you can see their list in arXiv and play the demos; the author search offers the document and associated materials in open: arXiv - search by Jacob Ginesin. To understand how GitHub presents and documents the verification of signatures in commitments, its official documentation page is a useful reference point: GitHub Docs - About commit signature verification. To check locally for commitment signatures and see how git handles verification, git documentation on git-verify-commit is practical: git-verify-commit.

Coverage

Related

More news on the same subject.