会,composer audit 仅扫描 composer.lock 中实际安装的传递依赖,且要求其为稳定版本并存在于 FriendsOfPHP/security-advisories 数据库中。

composer audit 会扫描传递依赖吗
会,但只扫 composer.lock 中实际安装的传递依赖,且前提是它们被收录进 FriendsOfPHP/security-advisories 数据库。audit 不解析 composer.json 的版本约束,它只比对锁文件里已确定的包名+版本号与已知漏洞清单。
这意味着:如果某个传递依赖(比如 psr/log)被 monolog/monolog 拉入,且其版本恰好在漏洞影响范围内,audit 就能报出来;但如果该包是 dev-main 这类开发分支版本,或使用了私有仓库未同步安全数据,audit 就直接跳过——不是漏报,是根本没纳入比对范围。
- audit 不关心“理论上可能装什么”,只看
composer.lock里“实际装了什么” - 传递依赖是否被扫描,和它在锁文件中是否存在、是否为稳定语义化版本、是否在 Packagist 安全库中有记录强相关
-
composer audit --no-dev仍会扫描生产依赖所带的全部传递依赖,只是不查require-dev下的工具链本身
怎么确认某个传递依赖是否被 audit 覆盖
别猜,直接查锁文件和数据库状态。最可靠的方式是三步交叉验证:
- 运行
composer show --tree | grep "target-package",确认该包确实出现在依赖树中,且有具体版本号(如psr/log v3.0.0) - 在
composer.lock中搜索该包名,检查其version字段是否为正式版(排除dev-、dev-master等),并确认source.type是git或package,而非dist+ 私有 URL - 手动查漏洞库:
curl -s "https://security.sensiolabs.org/api/advisories?package=target/package&version=3.0.0" | jq '.advisories[0].title'(需替换为真实包名和版本),看是否有返回
如果第三步无结果,audit 必然不会报它——哪怕你本地装了有漏洞的版本。
audit 报了传递依赖漏洞,但 composer why 找不到源头
常见于两种情况:一是该包被 replace 或 provide 声明覆盖(如 illuminate/support 被 laravel/framework 替代),二是它来自 require-dev 的间接链路,而你用了 --no-dev 参数导致审计路径断裂。
- 先跑
composer why --tree target/package,加--tree才能看到完整传递路径 - 再试
composer depends target/package,它比why更激进,会列出所有依赖该包的已安装项,包括 dev-only 包 - 如果仍为空,大概率是
replace关系:检查composer.lock中该包条目是否有"replaced": true或"provide"字段,然后顺着replaced by的包继续查
这种“看不见的依赖”最容易让人误判风险等级,必须追到 composer.lock 里的实际提供者才算闭环。
为什么升级主依赖后,audit 依然报同一传递依赖漏洞
因为 composer update vendor/main-package 默认不升级它的子依赖,除非显式加 --with-dependencies。Composer 锁定的是整棵树,不是单点。
- 执行
composer update vendor/main-package --with-dependencies,强制重解该包及其所有下游依赖 - 若仍不生效,检查
composer.lock中该传递依赖的source.reference是否还是旧 commit hash —— 有时包作者在 patch 版本里修了漏洞,但没发新 tag,只推了新 commit - 临时方案:用
composer require target/package:^new-fixed-version --update-with-dependencies强制指定版本,再验证 lock 文件是否更新
audit 的报告永远忠实于 lock 文件,而 lock 文件是否反映最新修复,取决于你执行 update 的粒度和范围——这点极易被忽略。











