vlog
← 返回全部文章

Tech

编译那一步就是运行那一步:Rust 最受信任的账号被借去投毒,窗口只开了 86 分钟

2026年8月22日 · 凯文·凯利《失控》~1 min read

8 月 20 日 07 点 15 分(UTC),crates.io 上多出三个新版本:arrayref 0.3.10、append-only-vec 0.1.9、internment 0.8.7。发布账号是 BurntSushi,也就是写出 ripgrep 的 Andrew Gallant,Rust 圈里最让人放心的名字之一。而这三个版本里各埋着一根引线:谁的构建机在这个早上照常跑 cargo build 拉到它们,编译还没结束,引线就着了。

30 秒读懂
1出事

86 分钟,投毒的包顶着一个最可信的名字挂在架上

从上架到下架,一顿早饭的工夫。

时间线短得反常:

时间(UTC)发生了什么
07:15三个恶意版本经被盗账号上架
08:41从索引移除,曝光窗口共 86 分钟
随后锁定被盗账号,清理攻击者名下的 crate

短,是因为抓得快。可你别看只有 86 分钟,全球的构建机没有上下班:CI 在跑、发布在跑、新项目在第一次拉依赖,这段时间里每一次解析到这三个新版本号的构建,都站在窗口里。老版本干净,毒只挂在新版本号上。

⚡

为什么值得看:这条链上每一环,你的项目里八成也有:一个人人都信的维护者、一块地基级的包、一段默认放行的构建脚本。这回是 Rust,换成 npm 或 PyPI,剧本一个字不用改。

2引线

你一个函数都没调,它在编译那一刻就跑了

毒不在库代码里,在构建脚本里。

三个恶意版本的改动小得可怜:各加了一个依赖,叫 proc-macro1。名字仿的是 David Tolnay 的 proc-macro2,Rust 生态最常用的库之一。一字之差,typosquat(蹭名)的老套路:正主写得堂堂正正,仿的那个才带毒。

核心

proc-macro1 的 build.rs 构建脚本:从 base64 还原出攻击者地址,走 TLS 拉取二级载荷,证书都不校验,在编译期执行。项目只要构建时解析到它,载荷就落地,三个 crate 的函数一个都不用调。

cargo 的规矩是,依赖树里任何一个包带构建脚本,编译时先跑它。这条路也不是 Rust 独一份:npm 的 install 脚本、Python 的 setup.py,走的都是同一类「装上即执行」的门。你审计代码,审的是「我调了什么」;这毒躲在「我编译了什么」里,差着一层,审不到。

旧认知

恶意包总得等我调用它的函数才作得了恶,引进来不用,顶多占点体积。

现实

毒在构建脚本里,cargo build 解析到它那一刻就执行;这三个版本里没有一行需要你调用的恶意代码。

有人要说了:我又不写宏、不搞元编程,proc-macro 系的包跟我有什么关系?这话恰好踩在坑沿上。被投毒的三个包,管的是数组引用、只增向量、字符串驻留,全是最普通的工具件;proc-macro1 是作为它们的新依赖被拖进来的,你从头到尾没有机会选它,甚至不会知道它来过。

打个比方

像装修进场的一批板材。你还没打算用它打柜子,可木工班的规矩是料一进场,先照厂家说明书做预处理。高仿板材的说明书头一条写的是:把这家的大门钥匙配一把,寄回厂家。坏事的不是板材,是「照说明书办」这条谁都没怀疑过的规矩。

3分量

2.45 亿次下载的地基砖,押在一份登录凭据上

攻击者挑中它,看上的正是名字背后的覆盖面。

arrayref 有多要紧?累计下载 2.45 亿次,近 90 天 5,370 万次,403 个 crate 把它列为直接依赖,再往下传出去的树没法数。你别看它拢共没几行代码,踩它的人太多,它才成了地基。

被盗的这个人,分量同样不一般。BurntSushi 在 Rust 社区的信誉攒了十几年,ripgrep 装在无数开发者的机器上。Rust 安全团队把话说得很明白:不认为 Gallant 本人作恶,几乎可以肯定是机器或凭据被盗。至于怎么盗的,是钓鱼、是哪台机器中了木马,还是别的路子,公开信息里没有定论;能确认的只有结果。

核心

2.45 亿次下载背后的信任,实际押在一台电脑、一份凭据的安全上。人没变,锁丢了。

下载量与 86 分钟曝光窗口取自 StepSecurity 的分析;处置动作以 crates.io 通报为准。
COMPILING IT WAS ENOUGH TO RUN ITON crates.io · ATTACKER SIDEYOUR MACHINE · BUILD TIMEMaintaineraccount stolencrates.ioMalicious releasesarrayref 0.3.10append-only-vec 0.1.9internment 0.8.7New dependencyproc-macro1fakes proc-macro2build.rsthe build scriptbase64 → decode addressTLS → 2nd-stage payloadno cert validationruns at compile time86 minexposure · 07:15–08:41 UTC245Marrayref all-time downloads53.7Mdownloads · last 90 days403crates depend on it directlyNo function call needed — dependency resolution is the trigger.
Source: The Hacker News / StepSecurity (2026-08-20). The malicious code hid in the build script of a dependency — the moment a build resolves it, it runs; no function call is ever needed.
4信任

包管理器把「我信这个人」放大成「我信这个账号发的一切」

信任的自动传递是效率,也是攻击面。

凯文·凯利在《失控》里写过:去中心化生态的力量来自互相依赖,信任像营养一样在网络里自动流动,不用谁居中审批,生态才长得快。crates.io 就是这样一张网。你信 BurntSushi,cargo 替你把这份信任自动续到他账号发的每个版本;403 个 crate 信 arrayref,几十万个项目没人过问就继承了这份信任。而且这份信任会滚利:越多人信 arrayref,新项目越敢闭眼引它,信它的人就更多。滚到 2.45 亿次下载,中间没有任何一环需要谁点头。效率是真效率。可管道不辨好坏,账号一丢,毒顺着同一套管道、以同样的速度,86 分钟灌向全球的构建机。

这事之后,社区又把一个老争论吵起来了:build.rs 凭什么能随意联网、任意执行?一派说这是生态跑起来的前提,多少包靠它找系统库、生成绑定;另一派说这就是每回投毒都能得手的原因。吵了不止一年,这回的案子给后一派又添了份证据。

我自己在这条管道上交过学费。2021 年我一个小工具的构建突然挂了:上游一个 npm 小包,作者删库跑路,打包机上恰好有缓存才没停摆。从那以后我把整个 node_modules 定期拷进一块移动硬盘,贴纸上写着俩字:别笑。这回的事让我把那块硬盘重新掂量了一遍。它防的是「包没了」,防不了「包变了」;真拉到投毒版本,它只会忠实地替我把毒多备一份。对付「变了」,得靠把版本钉死。

核心

crates.io 事后删除 6 个攻击者创建的 crate(proc-macro1、proc-macro-en、aovine、arone、aronenao、tinymember),移除 3 个恶意版本,锁定被盗账号。这一轮账算清了;让构建脚本随意联网的规则,还是原样。

5你能做的

这对你意味着什么

三件今天就能动手的事。

第一,lockfile 提交进仓库,CI 构建加 --locked(npm、pnpm 对应 frozen-lockfile)。版本钉死之后,上游发什么新版本都进不来,升级只发生在你主动动手那一次。这次 86 分钟的窗口,对钉死版本的项目就构不成自动中招的路径。钉死也有边界:总有要升级的一天,那一天你得睁着眼过。

第二,把升级依赖当一次正经变更来审。diff 里盯两样:版本号,还有新冒出来的传递依赖。proc-macro1 与 proc-macro2 一字之差,眼睛扫过去很容易放行;名字长得像大牌的新面孔,多看一眼再放。

第三,别默认信构建脚本。CI 上能锁网络出口就锁,构建阶段只放行 registry 的域名。这拦不住所有花样,但至少让「编译期偷偷外联」这条路变吵、变难,出事时日志里有迹可查。

这三条针对的都是「构建时自动拉到新恶意版本」这一条路径;86 分钟窗口内若已拉取并编译过,属于事件响应的范畴,本文不覆盖。

至于 BurntSushi,人没问题。可工具链认的从来只有账号这一档,账号是会丢的。在生态学会区分「人」和「账号」之前,你能攥在手里的,就是自己仓库里那份 lockfile。

本文框架取材自凯文·凯利《失控》;事件与数字来自 The Hacker News 与 StepSecurity(2026-08-20)的报道与分析,细节以原始报道为准。

技术

编译那一步就是运行那一步:Rust 最受信任的账号被借去投毒,窗口只开了 86 分钟

2026年8月22日 · 凯文·凯利《失控》约 6 分钟

8 月 20 日 07 点 15 分(UTC),crates.io 上多出三个新版本:arrayref 0.3.10、append-only-vec 0.1.9、internment 0.8.7。发布账号是 BurntSushi,也就是写出 ripgrep 的 Andrew Gallant,Rust 圈里最让人放心的名字之一。而这三个版本里各埋着一根引线:谁的构建机在这个早上照常跑 cargo build 拉到它们,编译还没结束,引线就着了。

30 秒读懂
1出事

86 分钟,投毒的包顶着一个最可信的名字挂在架上

从上架到下架,一顿早饭的工夫。

时间线短得反常:

时间(UTC)发生了什么
07:15三个恶意版本经被盗账号上架
08:41从索引移除,曝光窗口共 86 分钟
随后锁定被盗账号,清理攻击者名下的 crate

短,是因为抓得快。可你别看只有 86 分钟,全球的构建机没有上下班:CI 在跑、发布在跑、新项目在第一次拉依赖,这段时间里每一次解析到这三个新版本号的构建,都站在窗口里。老版本干净,毒只挂在新版本号上。

⚡

为什么值得看:这条链上每一环,你的项目里八成也有:一个人人都信的维护者、一块地基级的包、一段默认放行的构建脚本。这回是 Rust,换成 npm 或 PyPI,剧本一个字不用改。

2引线

你一个函数都没调,它在编译那一刻就跑了

毒不在库代码里,在构建脚本里。

三个恶意版本的改动小得可怜:各加了一个依赖,叫 proc-macro1。名字仿的是 David Tolnay 的 proc-macro2,Rust 生态最常用的库之一。一字之差,typosquat(蹭名)的老套路:正主写得堂堂正正,仿的那个才带毒。

核心

proc-macro1 的 build.rs 构建脚本:从 base64 还原出攻击者地址,走 TLS 拉取二级载荷,证书都不校验,在编译期执行。项目只要构建时解析到它,载荷就落地,三个 crate 的函数一个都不用调。

cargo 的规矩是,依赖树里任何一个包带构建脚本,编译时先跑它。这条路也不是 Rust 独一份:npm 的 install 脚本、Python 的 setup.py,走的都是同一类「装上即执行」的门。你审计代码,审的是「我调了什么」;这毒躲在「我编译了什么」里,差着一层,审不到。

旧认知

恶意包总得等我调用它的函数才作得了恶,引进来不用,顶多占点体积。

现实

毒在构建脚本里,cargo build 解析到它那一刻就执行;这三个版本里没有一行需要你调用的恶意代码。

有人要说了:我又不写宏、不搞元编程,proc-macro 系的包跟我有什么关系?这话恰好踩在坑沿上。被投毒的三个包,管的是数组引用、只增向量、字符串驻留,全是最普通的工具件;proc-macro1 是作为它们的新依赖被拖进来的,你从头到尾没有机会选它,甚至不会知道它来过。

打个比方

像装修进场的一批板材。你还没打算用它打柜子,可木工班的规矩是料一进场,先照厂家说明书做预处理。高仿板材的说明书头一条写的是:把这家的大门钥匙配一把,寄回厂家。坏事的不是板材,是「照说明书办」这条谁都没怀疑过的规矩。

3分量

2.45 亿次下载的地基砖,押在一份登录凭据上

攻击者挑中它,看上的正是名字背后的覆盖面。

arrayref 有多要紧?累计下载 2.45 亿次,近 90 天 5,370 万次,403 个 crate 把它列为直接依赖,再往下传出去的树没法数。你别看它拢共没几行代码,踩它的人太多,它才成了地基。

被盗的这个人,分量同样不一般。BurntSushi 在 Rust 社区的信誉攒了十几年,ripgrep 装在无数开发者的机器上。Rust 安全团队把话说得很明白:不认为 Gallant 本人作恶,几乎可以肯定是机器或凭据被盗。至于怎么盗的,是钓鱼、是哪台机器中了木马,还是别的路子,公开信息里没有定论;能确认的只有结果。

核心

2.45 亿次下载背后的信任,实际押在一台电脑、一份凭据的安全上。人没变,锁丢了。

下载量与 86 分钟曝光窗口取自 StepSecurity 的分析;处置动作以 crates.io 通报为准。
编译那一步,就是运行那一步crates.io · 攻击者一侧你的机器 · 构建时维护者账号被盗crates.io发布恶意版本arrayref 0.3.10append-only-vec 0.1.9internment 0.8.7新增依赖proc-macro1仿冒 proc-macro2build.rs构建脚本base64 还原地址TLS 拉取二级载荷不验证证书编译期执行86 分钟曝光窗口 07:15–08:41 UTC2.45 亿arrayref 累计下载5,370 万近 90 天下载403直接依赖它的 crate不需要调用任何函数——构建解析到依赖,就是触发
来源:The Hacker News / StepSecurity(2026-08-20)。恶意代码藏在依赖的构建脚本里——构建一旦解析到它,就会执行,不需要调用任何函数。
4信任

包管理器把「我信这个人」放大成「我信这个账号发的一切」

信任的自动传递是效率,也是攻击面。

凯文·凯利在《失控》里写过:去中心化生态的力量来自互相依赖,信任像营养一样在网络里自动流动,不用谁居中审批,生态才长得快。crates.io 就是这样一张网。你信 BurntSushi,cargo 替你把这份信任自动续到他账号发的每个版本;403 个 crate 信 arrayref,几十万个项目没人过问就继承了这份信任。而且这份信任会滚利:越多人信 arrayref,新项目越敢闭眼引它,信它的人就更多。滚到 2.45 亿次下载,中间没有任何一环需要谁点头。效率是真效率。可管道不辨好坏,账号一丢,毒顺着同一套管道、以同样的速度,86 分钟灌向全球的构建机。

这事之后,社区又把一个老争论吵起来了:build.rs 凭什么能随意联网、任意执行?一派说这是生态跑起来的前提,多少包靠它找系统库、生成绑定;另一派说这就是每回投毒都能得手的原因。吵了不止一年,这回的案子给后一派又添了份证据。

我自己在这条管道上交过学费。2021 年我一个小工具的构建突然挂了:上游一个 npm 小包,作者删库跑路,打包机上恰好有缓存才没停摆。从那以后我把整个 node_modules 定期拷进一块移动硬盘,贴纸上写着俩字:别笑。这回的事让我把那块硬盘重新掂量了一遍。它防的是「包没了」,防不了「包变了」;真拉到投毒版本,它只会忠实地替我把毒多备一份。对付「变了」,得靠把版本钉死。

核心

crates.io 事后删除 6 个攻击者创建的 crate(proc-macro1、proc-macro-en、aovine、arone、aronenao、tinymember),移除 3 个恶意版本,锁定被盗账号。这一轮账算清了;让构建脚本随意联网的规则,还是原样。

5你能做的

这对你意味着什么

三件今天就能动手的事。

第一,lockfile 提交进仓库,CI 构建加 --locked(npm、pnpm 对应 frozen-lockfile)。版本钉死之后,上游发什么新版本都进不来,升级只发生在你主动动手那一次。这次 86 分钟的窗口,对钉死版本的项目就构不成自动中招的路径。钉死也有边界:总有要升级的一天,那一天你得睁着眼过。

第二,把升级依赖当一次正经变更来审。diff 里盯两样:版本号,还有新冒出来的传递依赖。proc-macro1 与 proc-macro2 一字之差,眼睛扫过去很容易放行;名字长得像大牌的新面孔,多看一眼再放。

第三,别默认信构建脚本。CI 上能锁网络出口就锁,构建阶段只放行 registry 的域名。这拦不住所有花样,但至少让「编译期偷偷外联」这条路变吵、变难,出事时日志里有迹可查。

这三条针对的都是「构建时自动拉到新恶意版本」这一条路径;86 分钟窗口内若已拉取并编译过,属于事件响应的范畴,本文不覆盖。

至于 BurntSushi,人没问题。可工具链认的从来只有账号这一档,账号是会丢的。在生态学会区分「人」和「账号」之前,你能攥在手里的,就是自己仓库里那份 lockfile。

本文框架取材自凯文·凯利《失控》;事件与数字来自 The Hacker News 与 StepSecurity(2026-08-20)的报道与分析,细节以原始报道为准。

テクノロジー

编译那一步就是运行那一步:Rust 最受信任的账号被借去投毒,窗口只开了 86 分钟

2026年8月22日 · 凯文·凯利《失控》約 6 分

8 月 20 日 07 点 15 分(UTC),crates.io 上多出三个新版本:arrayref 0.3.10、append-only-vec 0.1.9、internment 0.8.7。发布账号是 BurntSushi,也就是写出 ripgrep 的 Andrew Gallant,Rust 圈里最让人放心的名字之一。而这三个版本里各埋着一根引线:谁的构建机在这个早上照常跑 cargo build 拉到它们,编译还没结束,引线就着了。

30 秒读懂
1出事

86 分钟,投毒的包顶着一个最可信的名字挂在架上

从上架到下架,一顿早饭的工夫。

时间线短得反常:

时间(UTC)发生了什么
07:15三个恶意版本经被盗账号上架
08:41从索引移除,曝光窗口共 86 分钟
随后锁定被盗账号,清理攻击者名下的 crate

短,是因为抓得快。可你别看只有 86 分钟,全球的构建机没有上下班:CI 在跑、发布在跑、新项目在第一次拉依赖,这段时间里每一次解析到这三个新版本号的构建,都站在窗口里。老版本干净,毒只挂在新版本号上。

⚡

为什么值得看:这条链上每一环,你的项目里八成也有:一个人人都信的维护者、一块地基级的包、一段默认放行的构建脚本。这回是 Rust,换成 npm 或 PyPI,剧本一个字不用改。

2引线

你一个函数都没调,它在编译那一刻就跑了

毒不在库代码里,在构建脚本里。

三个恶意版本的改动小得可怜:各加了一个依赖,叫 proc-macro1。名字仿的是 David Tolnay 的 proc-macro2,Rust 生态最常用的库之一。一字之差,typosquat(蹭名)的老套路:正主写得堂堂正正,仿的那个才带毒。

核心

proc-macro1 的 build.rs 构建脚本:从 base64 还原出攻击者地址,走 TLS 拉取二级载荷,证书都不校验,在编译期执行。项目只要构建时解析到它,载荷就落地,三个 crate 的函数一个都不用调。

cargo 的规矩是,依赖树里任何一个包带构建脚本,编译时先跑它。这条路也不是 Rust 独一份:npm 的 install 脚本、Python 的 setup.py,走的都是同一类「装上即执行」的门。你审计代码,审的是「我调了什么」;这毒躲在「我编译了什么」里,差着一层,审不到。

旧认知

恶意包总得等我调用它的函数才作得了恶,引进来不用,顶多占点体积。

现实

毒在构建脚本里,cargo build 解析到它那一刻就执行;这三个版本里没有一行需要你调用的恶意代码。

有人要说了:我又不写宏、不搞元编程,proc-macro 系的包跟我有什么关系?这话恰好踩在坑沿上。被投毒的三个包,管的是数组引用、只增向量、字符串驻留,全是最普通的工具件;proc-macro1 是作为它们的新依赖被拖进来的,你从头到尾没有机会选它,甚至不会知道它来过。

打个比方

像装修进场的一批板材。你还没打算用它打柜子,可木工班的规矩是料一进场,先照厂家说明书做预处理。高仿板材的说明书头一条写的是:把这家的大门钥匙配一把,寄回厂家。坏事的不是板材,是「照说明书办」这条谁都没怀疑过的规矩。

3分量

2.45 亿次下载的地基砖,押在一份登录凭据上

攻击者挑中它,看上的正是名字背后的覆盖面。

arrayref 有多要紧?累计下载 2.45 亿次,近 90 天 5,370 万次,403 个 crate 把它列为直接依赖,再往下传出去的树没法数。你别看它拢共没几行代码,踩它的人太多,它才成了地基。

被盗的这个人,分量同样不一般。BurntSushi 在 Rust 社区的信誉攒了十几年,ripgrep 装在无数开发者的机器上。Rust 安全团队把话说得很明白:不认为 Gallant 本人作恶,几乎可以肯定是机器或凭据被盗。至于怎么盗的,是钓鱼、是哪台机器中了木马,还是别的路子,公开信息里没有定论;能确认的只有结果。

核心

2.45 亿次下载背后的信任,实际押在一台电脑、一份凭据的安全上。人没变,锁丢了。

下载量与 86 分钟曝光窗口取自 StepSecurity 的分析;处置动作以 crates.io 通报为准。
ビルドした時点で、実行されていたcrates.io · 攻撃者側あなたのマシン · ビルド時保守者アカウント乗っ取りcrates.io悪意ある版を公開arrayref 0.3.10append-only-vec 0.1.9internment 0.8.7依存を追加proc-macro1proc-macro2 に偽装build.rsビルドスクリプトbase64 でアドレス復元TLS で第二段を取得証明書は未検証コンパイル時に実行86 分露出時間 07:15–08:41 UTC2.45 億arrayref 累計DL5,370 万直近 90 日のDL403直接依存する crate関数を呼ぶ必要はない——依存の解決そのものが引き金
出典:The Hacker News / StepSecurity(2026-08-20)。悪意あるコードは依存パッケージのビルドスクリプトに潜む。ビルドが依存を解決した時点で実行され、関数を呼ぶ必要はない。
4信任

包管理器把「我信这个人」放大成「我信这个账号发的一切」

信任的自动传递是效率,也是攻击面。

凯文·凯利在《失控》里写过:去中心化生态的力量来自互相依赖,信任像营养一样在网络里自动流动,不用谁居中审批,生态才长得快。crates.io 就是这样一张网。你信 BurntSushi,cargo 替你把这份信任自动续到他账号发的每个版本;403 个 crate 信 arrayref,几十万个项目没人过问就继承了这份信任。而且这份信任会滚利:越多人信 arrayref,新项目越敢闭眼引它,信它的人就更多。滚到 2.45 亿次下载,中间没有任何一环需要谁点头。效率是真效率。可管道不辨好坏,账号一丢,毒顺着同一套管道、以同样的速度,86 分钟灌向全球的构建机。

这事之后,社区又把一个老争论吵起来了:build.rs 凭什么能随意联网、任意执行?一派说这是生态跑起来的前提,多少包靠它找系统库、生成绑定;另一派说这就是每回投毒都能得手的原因。吵了不止一年,这回的案子给后一派又添了份证据。

我自己在这条管道上交过学费。2021 年我一个小工具的构建突然挂了:上游一个 npm 小包,作者删库跑路,打包机上恰好有缓存才没停摆。从那以后我把整个 node_modules 定期拷进一块移动硬盘,贴纸上写着俩字:别笑。这回的事让我把那块硬盘重新掂量了一遍。它防的是「包没了」,防不了「包变了」;真拉到投毒版本,它只会忠实地替我把毒多备一份。对付「变了」,得靠把版本钉死。

核心

crates.io 事后删除 6 个攻击者创建的 crate(proc-macro1、proc-macro-en、aovine、arone、aronenao、tinymember),移除 3 个恶意版本,锁定被盗账号。这一轮账算清了;让构建脚本随意联网的规则,还是原样。

5你能做的

这对你意味着什么

三件今天就能动手的事。

第一,lockfile 提交进仓库,CI 构建加 --locked(npm、pnpm 对应 frozen-lockfile)。版本钉死之后,上游发什么新版本都进不来,升级只发生在你主动动手那一次。这次 86 分钟的窗口,对钉死版本的项目就构不成自动中招的路径。钉死也有边界:总有要升级的一天,那一天你得睁着眼过。

第二,把升级依赖当一次正经变更来审。diff 里盯两样:版本号,还有新冒出来的传递依赖。proc-macro1 与 proc-macro2 一字之差,眼睛扫过去很容易放行;名字长得像大牌的新面孔,多看一眼再放。

第三,别默认信构建脚本。CI 上能锁网络出口就锁,构建阶段只放行 registry 的域名。这拦不住所有花样,但至少让「编译期偷偷外联」这条路变吵、变难,出事时日志里有迹可查。

这三条针对的都是「构建时自动拉到新恶意版本」这一条路径;86 分钟窗口内若已拉取并编译过,属于事件响应的范畴,本文不覆盖。

至于 BurntSushi,人没问题。可工具链认的从来只有账号这一档,账号是会丢的。在生态学会区分「人」和「账号」之前,你能攥在手里的,就是自己仓库里那份 lockfile。

本文框架取材自凯文·凯利《失控》;事件与数字来自 The Hacker News 与 StepSecurity(2026-08-20)的报道与分析,细节以原始报道为准。