This is episode thirteen of Git Good, Season Two.
Right now, on your computer, you can open a terminal and type two commands. Set your name to Linus Torvalds. Set your email to his public address at the Linux Foundation. Your next commit will look exactly like it came from the creator of Git himself. There is no password prompt. No verification step. No challenge. Git will accept whatever you tell it, write those values into the commit object, and never ask a single question about whether you are who you claim to be.
This is not a bug. This is not an oversight that the Git team forgot to fix. This is how Git was designed from the very first day.
Linus Torvalds built Git in two thousand five for a specific community. The Linux kernel developers. A few hundred people, most of whom had met each other at conferences, exchanged PGP keys in person, and built trust through years of public mailing list participation. In that world, identity was social. You knew who someone was because you had seen their patches, read their arguments, watched them earn credibility over months and years. Cryptographic verification existed for the moments that truly mattered, like signing a release tag, but for the daily flow of patches and commits, social trust was enough.
That was twenty years ago. Today, tens of millions of developers use GitHub. The vast majority of them have never met each other. They collaborate across continents, across time zones, across organizational boundaries. The social trust model that worked for a tight-knit kernel community does not scale to a planet. And Git still has not changed. It still trusts whatever you type into those two lines. It still does not check.
Here is what a Git commit actually stores about its author. Two strings of plain text. A name and an email address. That is it. No cryptographic link to a real identity. No token from an identity provider. No proof of any kind. Just text, stored alongside the code changes, treated with exactly the same level of trust as a comment in a config file.
The implications are straightforward. Anyone can claim any identity in any commit. You can attribute your work to someone else. You can attribute someone else's work to yourself. You can create a commit history that looks like a famous developer contributed to your project when they never heard of it. You can backdate commits to make it look like code was written months before it actually was. Both the identity and the timestamp are whatever you say they are.
This is not theoretical. Security researchers have demonstrated it repeatedly. In two thousand twenty-two, a team published a detailed walkthrough showing how to spoof any user on GitHub. Set the name and email to match a target's GitHub profile. Push a commit to a repository where they are listed as a collaborator. GitHub's interface shows their profile picture, links to their account, and displays the commit as if they made it. The only visual difference is the absence of a small green "Verified" badge, a distinction that most developers have never thought about and many have never noticed.
A separate researcher built a tool called gitfraud that automates the entire process. Feed it a GitHub username, and it generates commits attributed to that person. The tool exists not as an attack but as a demonstration of how thin the identity layer really is. Or rather, how there is no identity layer at all.
Think about what this means for a supply chain. When a developer reviews a pull request, they see a name and a profile picture attached to each commit. They trust that the person who wrote the code is who the commit says they are. That trust is not verified by Git. It is not verified by GitHub, unless the commit is signed. It is simply assumed. And assumptions, in security, are the thing that gets you compromised.
The fix exists. It has existed for over a decade. Commit signing allows a developer to attach a cryptographic signature to every commit, proving that the code was written by someone who controls a specific key. GitHub displays a green "Verified" badge on signed commits. The technology works. The math is sound. The tooling is available on every platform. And almost nobody uses it.
A research team published a study in two thousand twenty-five at the International Conference on Evaluation and Assessment in Software Engineering. They analyzed sixty popular open source repositories on GitHub across four domains, spanning five years of commit history. The finding was stark. Only about ten percent of all commits were signed.
The breakdown by domain tells the story even more clearly. In security-focused repositories, where the developers presumably understand the threat model better than anyone, twenty-eight percent of commits were signed. Better, but still barely a quarter. In web development repositories, roughly thirteen percent. In database projects, about six percent. And in machine learning repositories, two and a half percent. The developers building the AI systems that millions of people rely on sign fewer than three out of every hundred commits.
The researchers found something else that was arguably worse. After GitHub launched its "Verified" badge and vigilant mode in two thousand twenty-one, there was a brief uptick in signed commits. Developers noticed the feature, tried it out, set up their keys. Then, after early two thousand twenty-three, the trend reversed. Signing rates declined. The initial curiosity faded, the friction remained, and developers went back to unsigned commits.
The reasons are not mysterious. Setting up GPG commit signing is a genuinely unpleasant experience. You need to generate a keypair, configure your Git installation to use it, potentially set up a GPG agent so you do not have to type your passphrase on every commit, upload the public key to GitHub, and remember to maintain the key when it expires. If you work on multiple machines, you need the key on all of them. If you lose the key, your old signatures become unverifiable. The whole process feels like punishment for trying to do the right thing.
In August two thousand twenty-two, GitHub added support for signing commits with SSH keys. This was genuinely simpler. Most developers already have SSH keys for authenticating with GitHub. Using the same key, or a different one, for signing requires a few lines of Git configuration instead of the GPG gauntlet. It was the right idea. But even with SSH signing, the adoption numbers tell you that "simpler" is not the same as "simple enough." When the default is unsigned, and signing requires any setup at all, most developers will never do it.
There is one project on earth that has solved the identity verification problem for Git. It is the same project that Git was built for in the first place.
The Linux kernel maintains a web of trust that has no equivalent anywhere else in open source. When a subsystem maintainer finishes a set of patches and wants Linus Torvalds to pull them into the mainline kernel, they do not just push a branch. They create a signed tag. That tag carries a cryptographic signature proving that the maintainer reviewed and approved every commit in that branch. When Linus pulls, he verifies the signature. If the signature does not match a key he trusts, the pull does not happen.
But a signature is only as good as the key behind it. The kernel community maintains a dedicated repository of developer public keys, hosted on kernel.org. To get your key into that repository, it must carry at least one signature from someone whose key is already there. And that person's key must be traceable, through a chain of signatures, back to Linus Torvalds himself. It is a web of trust in the original sense. Every new participant is vouched for by an existing participant, and the chain ultimately anchors to the person at the top.
Torvalds himself has described this philosophy. For him, the identity behind a key matters less than the history of what that key has done.
It is a history of behavior rather than a collection of key-signing parties that builds trust for me.
This system works. It has protected the kernel through decades of contributions from thousands of developers across dozens of countries. It is also extraordinarily expensive in human terms. Maintaining PGP keys, attending key-signing parties at conferences, managing the web of trust as developers join and leave, all of it requires sustained effort from people who would rather be writing code. The kernel can afford this overhead because the stakes justify it and because the community has institutional memory stretching back decades.
Almost no other project does anything like it. The barrier is not technical. The tools exist. The barrier is cultural and organizational. Most open source projects are maintained by one person, maybe two, working in their spare time. Asking them to also maintain a cryptographic web of trust is asking them to do a second unpaid job on top of their first unpaid job.
Everything we have talked about so far, the spoofable identity, the unsigned commits, the gap between what is possible and what anyone actually does, all of it converges in a single story.
In two thousand twenty-one, a developer calling themselves Jia Tan started sending patches to the XZ Utils compression library. Good patches. Consistent patches. The kind of work that builds trust in any open source project. Over two years, Jia Tan earned commit access, became a co-maintainer, and then planted a backdoor that would have given an attacker remote access to every Linux server running the affected version. The severity score was ten out of ten. A Microsoft engineer caught it by accident, investigating a five hundred millisecond SSH delay that should not have been there.
The identity lesson is what matters for this episode. Git did not verify Jia Tan. GitHub did not verify Jia Tan. The mailing list did not verify Jia Tan. Sock puppet accounts pressured the exhausted solo maintainer into accepting help, and nobody checked whether the helpful stranger was who they claimed to be. The only verification was social. Jia Tan sent good patches, showed up consistently, and earned trust the same way every legitimate contributor earns trust. By doing the work. In Git's identity model, that was enough. Because in Git's identity model, that is all there is.
There are two ways to think about Git's trust model, and both of them are correct.
The first says that the openness is a feature. Git was built for a world where anyone can contribute. No gatekeeper decides who gets to write code. No identity authority grants or revokes permission. You show up, you send a patch, and the quality of your work speaks for itself. This is the open source ideal. Judge the code, not the credential. The fact that a teenager in Bangladesh and a senior engineer at Google look exactly the same in a Git log is not a bug. It is the entire point.
The second says that the openness is an invitation to exploitation. When identity is free and unverified, impersonation is trivially easy. When trust is built through social reputation alone, social engineering is the obvious attack vector. The XZ incident did not exploit a flaw in Git's code. It exploited the space where Git's philosophy meets reality. The belief that social trust would scale the way technical trust does.
Both of these views are true simultaneously, and that is what makes the problem so hard. Tightening identity verification makes Git safer but also makes it less accessible. Requiring signed commits would stop impersonation but would also stop the teenager in Bangladesh who does not have a GPG key and does not know what one is. Every security measure is also a barrier to entry. And Git's entire history is a story of lowering barriers.
There is a project called Sigstore that represents the most promising attempt to thread this needle. Instead of asking developers to manage long-lived cryptographic keys, which is the thing that killed GPG adoption, Sigstore uses what it calls keyless signing. You authenticate with an identity provider you already use, Google, GitHub, or Microsoft. A short-lived certificate is created, valid for only minutes. Your artifact is signed, the signature is logged in a public transparency ledger, and the key is destroyed. No key to manage. No key to lose. No key to expire and break your verification chain.
The elegance of the approach is that it shifts the question from "do you have a key?" to "can you prove who you are?" The first question requires setup, maintenance, and expertise. The second requires logging into an account you already have. Sigstore is already widely adopted for signing container images and software packages. Applying the same model to Git commits would eliminate the friction that keeps ninety percent of developers from signing anything.
But it would also mean trusting identity providers. Your Git identity would be anchored to a Google account or a GitHub account or a Microsoft account. For the kernel community, where independence from any single corporation is a core value, that trade-off might be unacceptable. For the tens of millions of developers who already log into GitHub every day, it might be exactly right.
The AI thread makes this even more complicated. When an AI coding assistant generates a commit, whose identity goes on it? The developer who prompted the AI? The AI provider? A bot account? If a signed commit means "I vouch for this code," what does it mean when the person signing it did not write the code and may not have read it carefully? The identity model was built for a world where people wrote code. In a world where machines write code and people review it, maybe review it, the meaning of identity in a commit is changing faster than the tools can keep up.
There is a gap in Git that has been there since two thousand five. On one side, you have a tool that stores identity as two lines of plain text, trusting whoever fills them in. On the other side, you have a world of tens of millions of developers, automated pipelines, AI agents, and nation-state attackers. The gap between those two realities has been growing for twenty years, and it is not getting smaller.
The Linux kernel closed the gap with a web of trust that costs enormous human effort to maintain. GitHub tried to close it with "Verified" badges and vigilant mode, but the opt-in design means the gap persists for the ninety percent who never set up signing. Sigstore offers a path that might work for the majority, but it trades one kind of trust for another. And the XZ attack showed what happens when someone decides to walk through the gap deliberately, patiently, over the course of two and a half years, building exactly the kind of social trust that Git relies on.
Episode eleven told you about the secrets hiding in Git's history. Episode twelve told you about who gets blamed when something goes wrong. This episode is about a more fundamental question. When a commit says it was written by a certain person, should you believe it?
Right now, for most of the world's code, the honest answer is that you do not know. You trust. You assume. You look at the name and the profile picture and the history of contributions and you make a judgment. The same kind of judgment that the XZ Utils community made about a developer named Jia Tan, who showed up, did good work, earned trust, and then used that trust to plant a backdoor that almost broke the internet.
The XZ story showed us where the identity gap leads. A patient attacker walked through it over two and a half years, building exactly the kind of social trust that Git relies on. Andres Freund's five hundred millisecond anomaly was the only thing that caught it. Git's identity model was not designed for a world where trust itself is the attack vector. But that is the world we live in.
That was episode thirteen of Git Good, Season Two.
Git log, show signature. Add that flag and your log output will include signature verification for every commit. Most of them will say "no signature." That is the point. The ones that do show a signature tell you that someone cared enough to set up signing and prove their identity cryptographically. In a world where anyone can claim any name in a commit, those green "Verified" badges are the closest thing Git has to proof. Whether that proof means anything depends on whether you trust the key, or the identity provider, or the web of trust behind it. But at least it is something. Which is more than the unsigned commits can say.