composer install默认不拦截恶意包,因其流程仅为下载→解压→注册autoload→执行脚本,无内置安全检查;真正防护依赖签名验证+allow-plugins白名单+自定义plugin实时钩子三者组合。

无法靠 composer install 自动拦截未经审核的依赖包——它默认不校验签名、不阻断可疑包、不扫描代码行为。真正起作用的是组合策略:签名验证 + allow-plugins 白名单 + 自定义 Plugin 实时钩子。
composer install 为什么默认不拦截恶意包
Composer 的 install/update 流程本质是“下载 → 解压 → 注册 autoload → 执行脚本”,全程无安全检查环节。哪怕 composer.lock 被篡改、包作者邮箱是 admin@gmail.com、autoload.files 指向 ./shell.php,它都照装不误。
- 签名验证默认关闭:2.5+ 版本才支持
security.signature-verification,但需手动开启,且只对 Packagist 上作者主动签名的包有效 - allow-plugins 不是“开关”,而是“闸门”:2.2+ 默认设为
{"*": false},所有插件(包括间接依赖带进来的)都会被拒绝,除非你显式授权 - composer audit 是事后扫描:只比对
composer.lock中版本是否匹配 FriendsOfPHP 数据库里的 CVE 条目,对未入库的 0day、混淆包、私有包完全无感
如何启用 Packagist 官方签名验证
签名验证是建立信任链的基础,但它只对作者启用了 signed packages 的包生效,且必须确认配置已落地。
- 运行
composer config -g security.signature-verification true全局开启(低于 2.5 的版本会报错Unknown configuration setting "security.signature-verification") - 检查是否生效:
composer show --security输出中必须含Signature verification: enabled - 私有仓库(如 Satis)不自动继承该机制,需额外配置
signing-key或启用仓库级签名策略 - 注意:签名只防篡改,不防作者主动投毒;若包作者账户被盗,签名依然有效
怎么用自定义 Plugin 实现安装前实时阻断
唯一能在包写入 vendor/ 前介入的事件是 PackageEvents::PRE_PACKAGE_INSTALL(2.5+ 稳定支持)。此时包尚未解压、autoload 尚未注册、脚本尚未执行。
- 监听该事件,在回调中检查:
package->getAuthors()[0]['email']是否匹配钓鱼模式(如admin@.*\.com)、package->getAutoload()['files']是否含可疑路径、package->getDist()['signature']是否为空或无效 - 任一条件命中,直接抛
RuntimeException,Composer 会立即中止当前包安装并退出整个流程 - 别依赖
scripts字段:恶意逻辑常藏在测试文件、注释、base64 字符串里,静态扫描极易漏 - 不要用
CommandEvent替代:v2.4 及以下需解析命令行参数,不稳定且易绕过
allow-plugins 白名单容易踩的坑
白名单不是“功能开关”,是执行许可。配置错误等于关掉全部防护。
- 错误写法:
"allow-plugins": true—— 这会让所有插件无条件加载,包括 transitive 依赖带进来的未知插件 - 正确写法:
"config": {"allow-plugins": {"symfony/flex": true, "laravel/pint": true}},包名必须完全匹配,不支持通配符(如"*/*") - 生产部署时,必须加
--no-plugins参数,且位置严格:composer install --no-plugins,不能写成composer --no-plugins install - 若某插件仍报错,说明它依赖另一个未授权插件,得顺藤摸瓜补全白名单,比如
phpunit/phpunit可能依赖phpunit/php-timer
真正卡住供应链攻击的点,不在“装完再查”,而在“装之前就拦”。签名验证、白名单、自定义 Plugin 这三者缺一不可——少一个,攻击者就能绕过整个防线。尤其要注意 composer.lock 文件本身可能已被污染,所以任何依赖检查都必须基于可信来源和运行时实时判断,而不是只信 lock 文件里的 hash。











