readlink 也能成为供应链入口:拆解 pnpm 的 POSIX bin shim

安全审计里,我们更常搜 evalexec 或拼接命令的代码。pnpm 的 POSIX 命令垫片揭示另一类汇点:内部辅助程序用"裸名称"执行,信任它们是系统版本,却把实际选择权交给了调用者的 PATH。如果依赖声明了 readlink 等同名 bin,甚至不用改业务的 build 脚本,也有机会改变某个垫片启动目标之前的执行步骤。

【事实】pnpm Issue #148372026-09-11 指出垫片头部裸名称调用 readlinkdirnamesedunamepnpm 12.4.22026-09-15正式发布主要 POSIX 路径的修复。

背景:什么是 bin shim

依赖包可以声明一个 bin,项目安装后 node_modules/.bin 出现可调用入口。pnpm 的垫片不仅转发执行,还要知道自己对应的包、解决符号链接、处理路径形式,再运行真正目标。因此,它是由包管理器生成、后来由项目脚本执行的代码制品,不只是一个静态链接。

【推断】团队审计依赖时习惯看安装脚本,但生成脚本中的外部命令调用也值得纳入可信工具链范围。此处并非断言所有包管理器采用相同头部,或者所有平台都遵守完全相同的 PATH 规则。

源码级拆解:哪些函数必须被信任

【事实】已合并修复 PR #148452026-09-13 解释了完整变更:旧头部根据调用者 PATH 寻找四种辅助程序;新的头部将 readlinkseduname 交给 command -p,而 dirname 改用 ${link%/*} 等 shell 参数展开,不再启动外部 dirname。跳过安装脚本时使用的 pnpm 占位垫片也曾以同样方式找 readlinkdirname,并纳入修复。

程序 原来在垫片中的作用 改变后的安全边界
readlink 解析垫片的符号链接目标 command -p 不从依赖 bin 优先查找
dirname 从链接和路径求目录 参数展开,不启动这个外部程序
sed 规范化路径分隔符等文本 command -p 在系统默认路径查找
uname 判断运行环境分支 command -p 在系统默认路径查找

command -p 是 POSIX shell 的搜索行为,不应在文章里写成"绝对路径白名单 /usr/bin"。参数展开减少外部进程数,也使原来的 dirname 入口不再存在。但改成更安全的查找策略仍需要处理兼容性 :PR 专门处理 $0 是裸名称时目录应为 . 的情形,并测试通过符号链接调用垫片的情况。

边界未闭合:cygpathwslpath

【事实】12.4.2 发布说明明确承认,在 Cygwin、MSYS2、WSL 的路径转换分支,辅助程序仍依赖 PATHPR #14845解释为何没有简单把 cygpathwslpath 也直接改成 command -p:这些工具在特定平台可能不处于 POSIX 系统默认路径,误改可能让垫片无法向原生 node.exe 传入可用路径。官方用 Issue #14866追踪剩余风险。

【推断】安全修复不仅要通过 Linux CI,也要把实际使用的跨平台 shell 和原生运行时组合纳入测试,否则"更安全的搜索"可能变成另一种可用性故障。残余问题需要单独的版本与配置判断,不能凭本文推测未来补丁发布日期。

安全案例:用无害标记验证不变量

无需生成恶意包。在隔离的代码审查中列出"垫片头部会启动的外部程序"和"程序从哪份搜索路径找到":

复制代码
before = {"readlink": "caller_PATH", "dirname": "caller_PATH",
          "sed": "caller_PATH", "uname": "caller_PATH"}
after = {"readlink": "system_default", "dirname": "shell_builtin_logic",
         "sed": "system_default", "uname": "system_default"}
assert all(after[x] != "caller_PATH" for x in before)

这是依据 PR 绘制的决策模型 ,不执行二进制、不联系包源,也不覆盖 cygpath/wslpath 的残余路径。真正的回归测试还应让 PATH 前部出现同名但无害的诱饵,断言目标包路径不变;PR 作者已描述这类负向测试,但本文不公开可投毒制品或攻击构造。

风险与行动建议

【事实】风险是"不可信依赖的同名 bin 可能先于原定目标运行",并可影响垫片最终执行的路径。实际发生须同时满足安装相应依赖、运行相关垫片和搜索顺序条件。发布资料没有给出在野利用、CVE 或正式 CVSS 评分。

【建议·P0】12 系列升级至确认的 12.4.2或更高版本,按发布说明重新安装依赖以替换旧垫片,抽查生成头部。对 WSL 等保留额外依赖准入及 Runner 隔离措施。

【建议·P1】开展"生成脚本源代码---安装后脚本制品"的双向审计,标出所有裸名称外部辅助命令、PATH 的来源、符号链接和路径转换分支。依赖包的 bin 字段也应接受代码评审,不只审查生命周期脚本。

【建议·P2】给内部垫片/封装脚本建立不变量测试:诱饵 PATH 不能改变辅助程序身份和最终目标;裸 $0、符号链接、Linux/macOS 与 Windows 兼容 shell 必须分别测试;维护者确认未修复分支的后续处置,而不是宣称单次提交覆盖全部平台。

总结

同样是四个普通工具名,安全问题不在名字,而在谁能决定它们指向哪个文件。pnpm 的修复让主要 POSIX 垫片把内部辅助程序从依赖可影响的搜索路径迁出;源码审计还要把生成文件、跨平台分支和旧文件替换连成同一个验收对象。

相关推荐
GLAB-Mary1 小时前
2026 华为热门认证方向测评:数通 / 安全 / 云计算 / AI / 存储,谁更适配未来就业?
安全·ai·云计算·华为认证·数通·存储
科技小登1 小时前
业务层四道闸:DDoS+CC、API、Bot 与全球加速的分层防护设计与选型
网络·安全
一只鹿鹿鹿1 小时前
信息系统网络安全检查表(Word)
大数据·安全·web安全·系统安全·制造
IT小白杨1 小时前
跨境电商账号关联归因链路拆解与可落地环境配置
服务器·网络·经验分享·安全·指纹浏览器
sbjdhjd1 小时前
从“删除后重生”到认证绕过:PHP 常驻内存实验与 Cacti remote_agent 命令执行链路复盘
安全·web安全·网络安全·数据挖掘·php·网络攻击模型·安全架构
Black蜡笔小新1 小时前
明厨亮灶落地指南:EasyCVR如何让后厨监控如何合规上云?
安全·音视频·easycvr
ai小陈2 小时前
GPU服务器租用安全配置实战:SSH密钥与端口最小化开放
服务器·人工智能·深度学习·安全·ai·gpu算力
ccino .2 小时前
Docker 容器删除卡在 Removal In Progress / Dead 解决
服务器·安全·web安全·网络安全
三掌柜6662 小时前
22秒攻击窗口下的防御重构:AI Threat Defense 与 Agent 安全护栏实践
人工智能·安全