The Hidden Gap in Git Security: Why SSH Certificates Can’t Verify Who Really Wrote Your Code

A technical analysis by Matthew Garrett reveals that Git's SSH certificate-based commit signing doesn't actually verify individual identity — only CA membership — creating a significant blind spot in software supply chain security that affects enterprises relying on SSH certificate infrastructure.
The Hidden Gap in Git Security: Why SSH Certificates Can’t Verify Who Really Wrote Your Code
Written by Emma Rogers

Matthew Garrett has a problem with Git. Specifically, he has a problem with the way Git handles cryptographic signatures — and if you’re running any kind of software supply chain that depends on knowing who committed what, you should probably have the same problem.

In a detailed technical post on his blog, Garrett — a well-known Linux kernel developer and security engineer — laid out a fundamental gap in how Git’s commit signing interacts with SSH certificates. The short version: Git can sign commits with SSH keys, and SSH supports a certificate authority model, but the two don’t actually work together in a way that lets you verify identity. The long version is considerably more uncomfortable for anyone who assumed this was a solved problem.

Git commit signing has been around for years. The original mechanism used GPG keys, which carried their own well-documented usability headaches. When Git added support for SSH key signing in 2021, it was widely welcomed. Developers already had SSH keys. The tooling was simpler. Organizations using GitHub or GitLab could point to existing key infrastructure. It felt like progress.

And in many respects, it was. But SSH key signing in Git has a structural limitation that Garrett’s post exposes with uncomfortable clarity.

Here’s the core issue. SSH supports two models for establishing trust. The first is the raw public key model — you trust a specific key because you’ve seen it before or someone told you to trust it. The second is the certificate model, where a certificate authority (CA) signs short-lived certificates that attest a given key belongs to a given identity. The certificate model is what most serious organizations want. It’s what underpins tools like Smallstep, Teleport, and Netflix’s BLESS. Short-lived credentials. Centralized identity attestation. No permanent keys sitting on developer laptops waiting to be exfiltrated.

Git’s SSH signing support, however, only really works with the first model. When you sign a Git commit with an SSH key, the verifier needs an allowed_signers file that maps public keys to identities. If you’re using plain SSH keys, this is straightforward — you list the keys you trust and the principals (email addresses, typically) they correspond to. Verification checks that the signature was made by a key in the allowed list.

Certificates complicate this. An SSH certificate contains the public key, the principal name, the CA signature, and validity constraints. In theory, you should be able to verify a commit signature by checking that the signing certificate was issued by a trusted CA for the claimed principal. In practice, Git doesn’t do this correctly.

Garrett’s post walks through the mechanics. When Git verifies an SSH signature against an allowed_signers file, it can be configured to trust a CA. You put the CA’s public key in the file with a cert-authority prefix. So far, so good. But the verification step doesn’t actually check that the principal in the certificate matches the identity claimed in the commit. Git asks ssh-keygen to verify the signature against the allowed_signers entry, and ssh-keygen will confirm that the signature was made by a certificate signed by the trusted CA — but it won’t enforce that the certificate was issued to the right person.

This means any valid certificate from the same CA can sign a commit claiming to be anyone else in the organization. A certificate issued to [email protected] could sign a commit attributed to [email protected], and Git’s verification would pass. The CA signature is valid. The principal mismatch goes unchecked.

That’s not a theoretical concern. It’s a supply chain integrity problem.

The implications ripple outward. Organizations adopting SSH certificates for infrastructure access — a trend that has accelerated significantly in recent years — might reasonably assume they can extend the same trust model to code signing. They can’t. Not without additional tooling or workarounds that Git doesn’t natively provide.

Garrett notes that the underlying ssh-keygen -Y verify command does support principal matching when invoked correctly. The problem is in how Git calls it. Git passes the committer identity and the allowed_signers file to ssh-keygen, but the interaction between certificate-based entries and principal verification doesn’t behave as expected. The result is a verification that confirms “this was signed by someone our CA trusts” but not “this was signed by the person who claims to have signed it.”

The distinction matters enormously. In a world increasingly focused on software supply chain security — driven by incidents like SolarWinds, the xz utils backdoor, and regulatory pressure from frameworks like SLSA and the U.S. executive order on cybersecurity — the ability to cryptographically verify the author of a commit is not a nice-to-have. It’s a requirement. And a verification system that confirms organizational membership but not individual identity falls short of what most security models demand.

This isn’t the first time the gap between SSH’s capabilities and Git’s implementation has drawn scrutiny. The Sigstore project, backed by the Open Source Security Foundation (OpenSSF), has been building an alternative approach to code signing that uses short-lived certificates tied to OIDC identity providers. Sigstore’s Gitsign tool takes a fundamentally different approach: instead of relying on SSH key infrastructure, it issues ephemeral signing certificates through the Fulcio CA and logs signatures to the Rekor transparency log. The identity binding comes from the OIDC token, not from the SSH certificate’s principal field.

But Sigstore adoption remains uneven, particularly inside enterprises that have already invested in SSH certificate infrastructure. For those organizations, Garrett’s findings present an awkward gap. They have the CA. They have the certificates. They have the identity attestation baked into their SSH infrastructure. And none of it actually flows through to Git commit verification in a meaningful way.

There are workarounds. One approach Garrett discusses is generating the allowed_signers file dynamically from certificate data, effectively pre-extracting the public keys and principals from issued certificates and building the trust file from that. This works but defeats much of the purpose of using certificates in the first place — you’re back to managing a list of individual keys, just with extra steps. Another option is wrapping Git’s verification in custom tooling that performs the principal check independently. Functional, but fragile and non-standard.

The right fix, Garrett argues, is in Git itself. The verification path needs to properly enforce principal matching when certificates are involved. This would likely require changes to how Git invokes ssh-keygen for verification, or potentially changes to ssh-keygen‘s verify mode to make principal enforcement more explicit in the certificate case.

Neither change is architecturally radical. But both require coordination between the Git and OpenSSH projects, and both require someone to do the work. Open source maintenance being what it is, “someone should fix this” can mean a long wait.

The timing of this disclosure is notable. GitHub has been expanding its support for SSH commit verification, including certificate-based signing, as part of a broader push toward verified commits. GitLab has similar features. Both platforms display verification badges on signed commits — the green “Verified” label that signals to reviewers and auditors that a commit’s authorship has been cryptographically confirmed. If the underlying verification doesn’t actually confirm authorship in the certificate case, those badges are misleading.

Supply chain security vendors have been building products and compliance workflows around commit signing verification. If those workflows rely on Git’s native SSH certificate verification without additional checks, they inherit this gap. Audit logs that show “verified” commits may not mean what auditors think they mean.

So where does this leave practitioners? A few concrete takeaways.

If you’re using SSH certificates for Git commit signing today, you should verify independently that your tooling checks principal matching. Don’t assume Git does it for you. If you’re using GPG-based signing, this specific issue doesn’t apply — GPG has its own trust model with its own set of problems, but principal binding isn’t one of them in the same way. If you’re evaluating Sigstore or similar transparency-log-based approaches, this is another data point in their favor: they were designed from the ground up for the code signing use case, rather than being adapted from an infrastructure authentication protocol.

And if you maintain Git or OpenSSH, Garrett’s post is essentially a well-documented feature request with security implications. The kind that tends to age poorly if left unaddressed.

The broader lesson here is one the security community keeps relearning. Composing two secure systems doesn’t automatically produce a secure system. SSH certificates are well-designed for authenticating users to servers. Git’s commit signing is a reasonable mechanism for attesting code authorship. But the seam between them — the place where one system’s assumptions meet the other’s implementation — is exactly where security guarantees quietly evaporate. Garrett has identified one such seam. There are almost certainly others.

For now, the green “Verified” badge on your Git commits might be telling you less than you think. Whether that matters depends on your threat model. For an increasing number of organizations, it matters quite a lot.

Subscribe for Updates

DevNews Newsletter

The DevNews Email Newsletter is essential for software developers, web developers, programmers, and tech decision-makers. Perfect for professionals driving innovation and building the future of tech.

By signing up for our newsletter you agree to receive content related to ientry.com / webpronews.com and our affiliate partners. For additional information refer to our terms of service.

Notice an error?

Help us improve our content by reporting any issues you find.

Get the WebProNews newsletter delivered to your inbox

Get the free daily newsletter read by decision makers

Subscribe
Advertise with Us

Ready to get started?

Get our media kit

Advertise with Us