当 GitHub Star 变成攻击信号:亲历 Sha1-Hulud 2.0 供应链攻击
本文经过结构整理与语言润色,原始内容提供了更完整与细致的真实经过与心路历程,记在了 2025 年 11 月 27 日记事中。
天上掉下的「馅饼」?
故事开始于 11 月 26 日早上。当我像往常一样打开 GitHub 时,通知栏里那一连串的 Star 消息瞬间占据了我的视线。我的项目 Focust 在短时间内突然增加了 123 个 Star。

说实话,那一刹那是幸福的。对于一个独立的学生开发者来说,这种突如其来的认可非常有诱惑力。看着这个数字,比我所有仓库加起来的零头还多,说不开心那是假的。
但理性的直觉很快压过了虚荣心——事出反常必有妖。我并没有在任何地方进行大规模推广,也没有大佬背书,这些 Star 来得太蹊跷,时间也高度重合。天上不会掉馅饼,这看起来更像是一个陷阱。
顺藤摸瓜:来自「僵尸」的伪装
为了验证猜想,我随机点开了几个点赞用户的主页。
乍一看,这些账号非常「正常」:有绿色的贡献瓷砖,有 Fork 记录,甚至有些看起来是正在认真钻研技术的学生账号。如果不仔细甄别,完全看不出异样。
但在连续翻阅了数个账号后,一个显著的统计学特征浮出水面,让我确信这绝非自然流量:
- Star 数量恒定:这些账号的 Star 数大多诡异地集中在 700-800 左右,多者上千,少有例外。
- 行为模式一致:查看他们的 Stars 列表,我发现他们几乎是对特定用户的仓库进行了「地毯式轰炸」。无论是热门项目还是已经废弃的 Fork,只要是该用户的仓库,一个不落全部 Star。
起初,我以为这只是有人购买了「刷赞」服务,并将我的项目作为掩护混在其中。毕竟,在黑产中,为了防止被风控,刷量的机器人通常会随机 Star 一些无关项目来模拟真人行为。
锁定目标:为什么是我?
「为什么是我?」这个问题始终萦绕在心头。为了寻找答案,我开始深入分析这些账号的 Star 列表,试图找出这几百个项目之间的最大公约数。
排除掉一些被定点轰炸的用户的仓库后,剩下的列表乍看杂乱无章。但在翻阅了几页后,技术栈的共性开始显现:
- Rust 语言出现频率挺高。
- 如果不使用 Rust,则主要是 TypeScript、Vue 或 Svelte 等。
而经过抽样检测,这些项目几乎无一例外都是 Tauri 应用、插件或模板。
当翻到我曾在一处清单列表中见过的另一个 Tauri 项目 blink-eye 时,我的猜想得到了进一步印证。这些项目都有一个共同点:它们都出现在 Awesome Tauri 的列表中。
所谓的「馅饼」,其实是一份基于 Awesome 列表生成的「死亡名单」。我的项目因为被收录其中,不幸(或者说幸运地)成为了这波异常流量的波及对象。
图穷匕见:第二波攻击与恶意签名
如果说上午的 Star 激增只是让人困惑,那么下午发生的事情则彻底暴露了攻击者的恶意。
大约在 13:36,第二波 Star 袭来。这次我注意到部分用户的个人主页出现了极度反常的信息:
- 仓库描述被篡改:多个受害者的仓库描述被统一修改为
F**K Guillermo, F**K VERCEL --multi(Guillermo 为 Vercel CEO)。 - 植入广告:部分仓库的 README 被恶意植入
# Free AI at api.airforce及一个过期的 Discord 邀请链接。
查看 Commit 历史,我发现攻击者使用了 Linus 的名义进行了 force push 掩盖痕迹:

当然,这并不能真正地清洗掉罪证,GitHub Activity 清晰地记录着罪行:

GPG 签名
由此可见 GPG 签名的重要性。虽然 Git 允许任何人配置 user.name 和 user.email 来伪造提交者身份,但在 GitHub 上,没有经过 GPG 私钥签名的提交虽然会显示名字,但不会显示绿色的 "Verified" 标签。这次攻击中,冒充 Linus 的提交显然是未经验证的。

真相大白:Sha1-Hulud 2.0 供应链攻击
通过搜索恶意广告信息,我顺藤摸瓜找到了云安全公司 Wiz 刚刚发布的报告:Sha1-Hulud 2.0 Supply Chain Attack: 25K+ Repos Exposed | Wiz Blog。
真相令人不寒而栗。这不仅仅是刷 Star,而是一场大规模的 NPM 供应链攻击:
- 窃取令牌:攻击者通过钓鱼窃取了 NPM 包作者的 Token。
- 恶意更新:发布包含恶意
preinstall钩子的新版本。 - 感染扩散:当其他开发者(也就是给我点 Star 的那些账号的主人)安装这些受感染的包时,恶意脚本会在安装阶段执行,窃取系统中的隐私信息(如 GitHub Token、AWS 凭证等)。
- 利用受害者:受害者的 GitHub 账号随即被攻击者接管,用于进一步扩散病毒、发布恶意广告,以及——莫名其妙地——给 Tauri 生态系统的项目刷 Star。
Wiz 的报告中后面补充提到了我观察到的刷 Star 现象:
Some of these accounts also appear to have been used to "boost" the star counts of projects in the Tauri ecosystem. (h/t pilgrimlyieu)
深度数据取证:揭开攻击的冰山一角
虽然知道了原理,但我对「Awesome 列表即死亡名单」的猜想仍需验证。为了探究攻击者的行为逻辑,我编写了一套数据分析工具,对 101 名受害者账号进行了数据快照与交叉分析(受害者 GitHub 账号数据均已加密)。
通过对数万条 Star 记录的清洗与挖掘,一些令人咋舌的规律浮出水面。
数据证实,这绝非随机的无差别攻击,而是针对特定技术生态的「定点选择」。通过将受害者的 Star 记录与 GitHub 上的 Awesome 列表比对,重合度高得惊人:
| 列表 | 攻击总数(次) | 被攻击的仓库(个) | 仓库总数(个) | 覆盖率 |
|---|---|---|---|---|
| Awesome FastAPI | 12,346 | 127 | 134 | 94.78% |
| Awesome Tauri | 24,638 | 244 | 283 | 86.22% |
在「被攻击仓库所有者」的数据中,你可以看到极度夸张的长尾分布。绝大多数开发者只是承受了这 101 个受害者对其中一个或少数几个仓库的的攻击,但有几个账号的数据异常突兀:

下面是被攻击 star 总数在 1k 以上的九位用户:
| 所有者 | 被攻击的 star 总数 |
|---|---|
| arpitbbhayani | 18,240 |
| Hrishikesh332 | 13,973 |
| linus | 3,840 |
| andrew | 3,267 |
| Welding-Torch | 2,548 |
| anxkhn | 2,198 |
| hanzalahwaheed | 2,063 |
| Ratheshan03 | 1,888 |
| ninadnaik10 | 1,712 |
翻了一下这些用户的特征:
- arpitbbhayani: 印度人,GitHub 与 X 上地址印度班加罗尔
- Hrishikesh332: 印度人?X 地址德国柏林,最近的推文表明他对孟买「了如指掌」
- linus: 瑞典人?GitHub 地址瑞典斯德哥尔摩
- andrew: 英国人?GitHub 地址英国布里斯托尔,有一个 ultimate-awesome 仓库
- Welding-Torch: 印度人,GitHub 简介显示印度孟买
- anxkhn: 印度人,GitHub 地址印度孟买
- hanzalahwaheed: 印度人?博客显示在阿联酋迪拜或印度班加罗尔工作
- Ratheshan03: 斯里兰卡人,GitHub 地址斯里兰卡科伦坡
- ninadnaik10: 印度人,GitHub 地址印度孟买
这也解释了我最初观察到的现象:大量账号被用来给这几位用户的仓库「刷榜」,而我只是因为身在 Awesome 列表中而被顺带「波及」。
我还分析了被攻击仓库的受攻击频次。大部分目标仓库被攻击了 80-100 次,而在第 783 位到 784 位之间出现了剧烈的断层(从 80 次骤降至 35 次)。这完美印证了我最初肉眼观察到的「Star 数目都在八百上下」的直觉。
| 序号 | 目标仓库 | 攻击次数 |
|---|---|---|
| … | … | … |
| 775 | Hrishikesh332/XRay_Efficient |
88 |
| 776 | torvalds/libgit2 |
80 |
| … | … | … |
| 783 | torvalds/1590A |
80 |
| 784 | devout-coder/shelly |
35 |
| … | … | … |
| 1094 | ninadnaik10/FireSense |
26 |
| 1095 | Hiral25p/bit-n-build-hackathon |
19 |
技术复盘与防御建议
这次经历是一次奇幻的「过山车」。虽然我很幸运地没有引入受感染的 NPM 包,但这次事件给所有开发者敲响了警钟。作为开发者,我们可以做些什么?
- 警惕
preinstall脚本:此次 Sha1-Hulud 2.0 变种病毒主要依赖package.json中的preinstall生命周期钩子执行。建议在 CI/CD 环境中限制或禁用不必要的生命周期脚本。 - Token 最小权限原则:NPM 官方即将在 12 月 9 日强制废除经典 Token,全面转向更细粒度的权限管理。请尽快迁移,并养成定期轮换 Token 的习惯。
- 拥抱 GPG 签名:配置 GPG 签名并开启 GitHub 的 Vigilant mode(警惕模式),让任何冒充你的 Commit 无所遁形。
结语:信誉是开源的基石
我曾想过,如果不去深究,保留这 100 多个 Star 是否也没关系?
但我很快否定了这个想法。在开源社区,Star 是货币,但信誉才是金本位。如果一个项目的 Star 数据充斥着虚假的水分,哪怕是被动的,也会让其他开发者降低对该项目的评价。
我宁愿要一个真实的数据,也不愿成为黑产链条上被利用的一环。换位思考,我不希望我的项目被人误解为刷量造假。目前,我已经看到部分受害者的账号开始恢复,我的 Star 数也随之回落。
看着数字减少,我反倒觉得安心了。因为我知道,剩下的每一个 Star,背后都是一个真实的、认可我代码的人。