一枚被劫持的 Python 包,撕开了开源供应链最危险的一道口子

安全 2026年3月28日
通信开发常用的 Python 包 telnyx 在 PyPI 上遭到投毒,看起来像是一起普通的软件供应链攻击,但它更像是一场持续蔓延的“自动化接管实验”。从 Trivy 到 npm,再到 PyPI,攻击者 TeamPCP 展示的不是单点破坏,而是把开发者信任链变成感染链的能力,这才是最让人不安的地方。

一次包更新,背后却是一场接力式渗透

如果你这两天正好在维护 Python 项目,看到 telnyx 这个包的更新,最好先倒吸一口凉气。根据 Aikido 的披露,热门通信开发包 telnyx 在 3 月 27 日凌晨于 PyPI 上出现了被恶意上传的版本,而背后的操盘者,正是最近在开源世界里四处点火的 TeamPCP。

telnyx 这个名字对很多开发者并不陌生。它服务于云通信场景,常见于短信、语音、号码管理等业务集成里。换句话说,这不是某个边角料项目,而是会出现在真实生产环境里的依赖。一旦它被投毒,受影响的就不只是某个开发者本地环境,而可能是 CI/CD、云函数、容器镜像,甚至客户数据触达链路。

这起事件之所以刺眼,不只是因为“又一个包中招了”,而是因为它被放进了一个更大的背景里:这已经不是零散的供应链攻击,而是一场跨生态、可复制、带有蠕虫特征的连续行动。Aikido 的判断很直接——攻击者的套路已经成型:先窃取可信工具的凭证,再用这些凭证去污染它能接触到的更多包,随后从新的受害环境里继续收集更多令牌和密钥,像滚雪球一样扩散。

说得不夸张一点,这已经有点像软件世界的“丧尸片开场”:最初只是一个人咳嗽,几天后整座城市都开始不对劲。

从 Trivy 到 npm 再到 PyPI,攻击链正在跨生态奔跑

Aikido 给出的时间线很有代表性。3 月 19 日,开源漏洞扫描工具 Trivy 遭到入侵,相关事件还被赋予了 CVE-2026-33634,CVSS 评分高达 9.4。攻击者借由被植入后门的版本,从未做严格版本锁定的 CI/CD 流水线中窃取凭证。这一步非常关键,因为它把“扫描工具”变成了“钥匙收集器”。

第二天,TeamPCP 就把这些偷来的令牌带到了 npm 世界,投放了名为 CanisterWorm 的后门,并在数十个 npm 包里完成发布。最夸张的地方在于自动化能力:一旦拿到某个 npm token,恶意程序会迅速枚举该令牌有权发布的所有包,自动升级版本号并完成发布。Aikido 提到,这个过程甚至能在 60 秒内完成。对开发者来说,这几乎意味着你还没来得及喝完一口咖啡,自己的发布权限就可能被借去污染整个 scope。

如今战火烧到 PyPI,telnyx 只是最新一块倒下的牌。把这些点连起来看,就会发现 TeamPCP 并不是在追求一次性破坏,而是在验证一件更可怕的事:不同包管理生态之间,本质上都建立在“凭证 + 信任 + 自动更新”这套机制上,而这套机制可以被同一种方法反复利用。

很多企业过去对供应链安全的理解,还停留在“别引入太冷门的包”或者“看一下 star 数量”。但这轮攻击提醒大家,真正危险的未必是默默无闻的小包,反而可能是被广泛使用、看上去非常正统、甚至带着官方光环的依赖。攻击者最爱下手的,从来都是大家最不设防的地方。

为什么 telnyx 这类包被劫持,杀伤力会特别大

供应链攻击最阴险的一点,是它往往披着“正常更新”的外衣。你不会看到一个黑客跳出来敲门说“你好,我来窃取环境变量了”。你看到的只是 CI 日志里一行普通的 pip install -U,或者某次镜像构建时自动拉下来的新版本依赖。表面看一切正常,内部却可能已经开始读取令牌、上传主机信息、探测运行环境,甚至准备向下一跳扩散。

telnyx 这种通信类 SDK,常常会出现在与客户交互强相关的系统里,比如验证码服务、客服呼叫、通知系统。它们运行的位置通常比较敏感:拥有 API 密钥、访问生产配置、连接云资源。攻击者如果能借此进入企业环境,拿到的就不只是某个开发者的机器信息,而可能是一整串业务控制权。

更令人头疼的是,很多团队对“官方包”会天然降低警惕。毕竟和某些匿名维护者上传的小众项目相比,企业品牌包、成熟 SDK、知名安全工具,听上去总让人觉得更稳。但这几年反复发生的事实是,攻击者越来越不热衷于伪装成别人,他们更愿意直接拿下真的“别人”。这比起传统的 typo-squatting——比如故意注册一个和知名包拼写很像的名字——成功率高得多,杀伤范围也大得多。

这也是为什么我认为,这起事件的重要性不亚于某个严重漏洞曝光。漏洞至少还有边界、有版本范围、有补丁路径;而当信任本身变成攻击入口时,开发流程里很多默认假设都会一起失效。你以为自己在升级依赖,实际上可能是在替攻击者更新投递渠道。

那个藏在细节里的信号:软件供应链已经进入“工业化作案”阶段

原文还提到一个耐人寻味的技术细节:攻击载荷中存在所谓的 “WAV trick”。从安全研究的经验看,这类做法通常意味着攻击者在努力把恶意内容伪装成更不显眼的数据或资源文件,以绕过简单的特征扫描和人工审查。今天它可以伪装成音频相关内容,明天也可能藏在图片、测试资源、模型权重甚至文档生成脚本里。攻击者越来越熟悉开发者的心理:大家对源码会多看两眼,对“资源文件”往往就一带而过。

这也是近两年供应链攻击的一条明显演进路线:不再只是简单塞一段明目张胆的窃密脚本,而是开始考虑持久化、逃逸、自动传播和隐蔽性。换句话说,攻击者正在像做产品一样打磨恶意软件。CanisterWorm 这样的命名,也不是随便起着玩,它在描述一种能力——像蠕虫那样自传播,遇到权限就接管,遇到令牌就复制自己。

如果说早年的开源供应链安全问题,更像是“野路子黑客顺手投毒”,那今天这批行动已经更接近一条成熟流水线:入侵上游、搜刮密钥、自动发版、跨生态横跳、持续收集新凭证。它不再是单一事件,而是方法论。对企业安全团队来说,这种变化意味着传统的“事件响应”思路已经不够用了,因为你面对的不是一个洞,而是一张在移动的网。

这也带出一个值得行业认真讨论的问题:我们今天的软件发布体系,是不是把“方便”押注得太彻底了?自动拉取最新依赖、共享发布权限、长期有效 token、缺乏强制签名校验,这些年都在提升开发效率,但在攻击者眼里,它们像一条铺好的高速公路。开发者社区常说“不要让安全拖慢创新”,可现实正在反问另一句话:如果完全不踩刹车,创新会不会直接冲出护栏?

对开发者和企业来说,现在最现实的不是愤怒,而是收拾现场

遇到这种事,很多人第一反应是问:那我该不该停止用开源?答案当然是否定的。现代软件几乎不可能脱离开源生态,问题从来不是“用不用”,而是“怎么用得不那么天真”。

对已经依赖 telnyx 的团队,最先要做的是确认自己拉取的版本、安装时间和执行环境,检查 CI/CD 日志、构建缓存、容器镜像层,以及安装时暴露过哪些环境变量和密钥。任何与 PyPI、云平台、代码托管平台、第三方通信服务相关的令牌,都应该进入轮换范围。这里最容易犯的错误是只删包不换钥匙。可一旦恶意代码已经运行,包本身往往只是案发现场,真正被偷走的可能是门禁卡。

再往前走一步,企业应该重新审视几件曾经被当成“最佳实践可选项”的东西:依赖版本锁定、最小权限发布、短周期凭证、2FA、构建隔离、对安装脚本和发布行为做审计。尤其是版本锁定,过去很多团队嫌麻烦,觉得影响更新速度;但在今天,它已经越来越像一条低成本的生命线。至少在攻击发生的第一时间,它能帮你挡住“自动吃到毒版本”这件事。

我也越来越倾向于认为,包仓库平台本身必须承担更主动的责任。无论是 PyPI、npm 还是其他生态,单靠维护者自觉已经不够了。更严格的发布行为异常检测、默认强制多因素认证、包签名和来源证明、敏感包的风险分级监控,这些机制不该再停留在倡议层面。开源生态当然珍贵,但“开放”不是“放养”。

说到底,这次 telnyx 事件并不只是某个 Python 包倒霉,而是再次提醒我们:当软件世界把一切都做成自动化流水线,攻击者也会把入侵做成自动化流水线。过去我们总爱说“代码即基础设施”,现在恐怕还要补一句——依赖链,也已经是战场本身。

Summary: 我对这起事件的判断是:它的危险不在于单个恶意版本,而在于攻击模式已经完成了跨生态验证。TeamPCP 展示的是一种可复制、可自动化、可规模化的供应链接管方法。如果包仓库、工具厂商和企业团队还把这类事件当成偶发事故,接下来只会看到更多“知名包突然中毒”的新闻。未来一年,依赖签名、发布凭证治理和默认版本锁定,很可能从安全加分项变成开发基础设施的必修课。
开源供应链攻击PyPItelnyxTeamPCPPython 包投毒凭证窃取CI/CDAikidonpmTrivy