GitHub 提交验证逻辑缺陷及绕过方法
我知道 Git 并不是为了像 GitHub 这样运作而设计的,而伪造问题也是多年来一直存在的老问题。对于 Shai Hulud 和 AI Agent,这次情况有些严重,因为如果没有启用警惕模式(Vigilant Mode)并且没有注册 GPG 密钥,提交验证也可能被伪造。
我理解平台和 Git 本身存在一些限制,但设计决策和设计缺陷是完全不同的事情。面对令人沮丧的漏洞奖励报告被驳回,以及 MSRC 将提交验证作为缓解措施的讽刺性品牌,我已经等了很久才在这里发帖。
GitHub 显然有机会通过与平台认证令牌和用户注册邮箱关联来进行验证,但他们选择不这样做。更具讽刺意味的是,当我等待对此问题的更多关注时,GitHub 被黑客攻击,这种联系真是无价之宝。
以下是正式的内容:
---------------------------------------------------
GitHub 自己的文档建立了一系列信任假设,按照逻辑推导,揭示了一个无法审计、无法程序化检测的验证漏洞,任何拥有免费账户的 GitHub 用户都可以利用。
文档中的链条:
1. GitHub 文档指出,提交签名验证让其他人“可以确信这些更改来自可信来源”:
https://docs.github.com/en/authentication/managing-commit-signature-verification
2. 验证检查提交是否使用注册到 GitHub 账户的 GPG/SSH 密钥签名:
https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification
3. Git 每个提交有两个身份字段:作者(编写代码的人)和提交者(应用代码的人)。这两个字段可以通过环境变量自由设置——GIT_AUTHOR_NAME、GIT_AUTHOR_EMAIL、GIT_COMMITTER_NAME、GIT_COMMITTER_EMAIL:
https://git-scm.com/book/en/v2/Git-Internals-Environment-Variables
4. GitHub 的用户界面显著显示作者。提交者则隐藏在二次点击之后。绿色的“已验证”徽章位于作者的名字和头像旁边。
5. GitHub 的验证仅绑定于提交者的密钥。作者字段没有经过验证、没有被验证,也没有受到限制。API 直接暴露这一点——作者、提交者和验证是每个提交上的独立对象:
https://docs.github.com/en/rest/git/commits
逻辑缺陷:
徽章在作者的名字旁边显示“已验证”——但它验证的是提交者的密钥。这两者可以是完全不同的人。GitHub 自己的 API 确认了这一点:一个提交可以返回 author=torvalds,committer=<ANYONE>,verification.verified=true。用户界面显示 Linus Torvalds 旁边有一个绿色的勾号。签名密钥是我的。
这并不是加密中的错误。GPG 签名是有效的。缺陷在于“已验证”所传达的信息与实际检查的内容之间的差异。
GitHub 知道这一点——并将防御措施设置在受害者的后面:
GitHub 实际上有一个“部分验证”徽章状态。当作者与提交者不相等且作者启用了警惕模式时会触发:
https://docs.github.com/en/authentication/managing-commit-signature-verification/displaying-verification-statuses-for-all-of-your-commits
这意味着 GitHub 意识到作者与提交者不匹配是一个信任问题。但该防御措施是选择性启用的,默认关闭,并且依赖于被冒充用户的账户设置——而不是攻击者的。攻击者通过选择未启用警惕模式的受害者来控制防御措施是否生效。Linus Torvalds 没有启用,绝大多数 GitHub 用户也没有。
查看原文
I know Git is not designed to use in the way GitHub is operating under and the spoofying had been an old issue that had been brought up throughout the years. With Shai Hulud and AI Agent, this time is abit more serious as the commit verification can be spoofed as well if you did not op in Vigilant Mode AND with a registered GPG key.<p>I understand there are limitations to platform and the Git itself, but design decision and design flaw are totally different things. With the very frustrating bug bounty report dismissal and the ironic branding of commit verification as a mitigation method by the MSRC, I had waited long enough to post it here.<p>GitHub clearly have the chance to do verification associating with the platform auth token and the user registered email but they chosen not to. And adding even more irony they (GitHub) got hacked when I was waiting for more engagement in this issue that ties to this hacked look is priceless.<p>Here's the formalized body:<p>---------------------------------------------------<p>GitHub's own documentation establishes a chain of trust assumptions that, followed to their logical conclusion, reveals a verification gap that cannot be audited, cannot be programmatically detected, and is available to any GitHub user with a free account.<p>The documented chain:<p>1. GitHub docs state that commit signature verification lets other people "be confident that the changes come from a trusted source":
https://docs.github.com/en/authentication/managing-commit-signature-verification<p>2. Verification checks whether the commit is signed with a GPG/SSH key registered to a GitHub account:
https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification<p>3. Git has two identity fields per commit: author (who wrote the code) and committer (who applied it). Both are set freely via environment variables — GIT_AUTHOR_NAME, GIT_AUTHOR_EMAIL, GIT_COMMITTER_NAME, GIT_COMMITTER_EMAIL:
https://git-scm.com/book/en/v2/Git-Internals-Environment-Variables<p>4. GitHub's UI displays the author prominently. The committer is hidden behind a secondary click. The green "Verified" badge sits next to the author's name and avatar.<p>5. GitHub's verification binds only to the committer's key. The author field is not verified, not validated, and not constrained. The API exposes this directly — author, committer, and verification are separate objects on every commit:
https://docs.github.com/en/rest/git/commits<p>The logic flaw:<p>The badge says "Verified" next to the author's name — but it verified the committer's key. These can be two completely different people. GitHub's own API confirms this: a commit can return author=torvalds, committer=<ANYONE>, verification.verified=true. The UI shows Linus Torvalds with a green checkmark. The signing key is mine.<p>This is not a bug in the crypto. The GPG signature is valid. The flaw is in what "Verified" communicates versus what it actually checks.<p>GitHub knows about this — and gated the defense behind the victim:<p>GitHub actually has a "Partially verified" badge state. It triggers when author ≠ committer and the author has enabled vigilant mode:
https://docs.github.com/en/authentication/managing-commit-signature-verification/displaying-verification-statuses-for-all-of-your-commits<p>This means GitHub is aware that author-committer mismatch is a trust problem. But the defense is opt-in, off by default, and gated on the impersonated user's account settings — not the attacker's. The attacker controls whether the defense fires by choosing victims who haven't enabled vigilant mode. Linus Torvalds hasn't. Neither have most GitHub users.