composer audit是唯一官方支持的依赖漏洞扫描命令,但必须同时满足composer≥2.5.0、全局启用experimental.audit、项目存在有效composer.lock三条件才可用,否则报错或静默失效,且仅比对lock文件精确版本与friendsofphp安全数据库。

composer audit 是唯一能直接用的官方命令,但它不是“装完就能扫”,多数人跑不出结果,根本原因就三个:版本不够、配置没开、锁文件不对。
怎么确认 composer audit 真的可用
别猜,直接验证三件事:
- 运行
composer --version:必须输出Composer version 2.5.0或更高;2.4.x 及更低版本压根没这个命令 - 运行
composer list | grep audit:没输出 = 命令未注册,即使版本达标也白搭 - 若前两项都满足但依然报
Command "audit" is not defined,执行composer config --global experimental.audit true—— 这会写入全局auth.json,缺了它,扫描逻辑不触发
某些定制版 composer.phar(比如锁定 PHP 7.2 的旧镜像)可能根本没编译审计模块,self-update 会失败,只能换官方完整版。
composer audit 扫的是 composer.lock,不是 vendor/
它完全不读 vendor/ 目录里的文件,只比对 composer.lock 中记录的精确包名 + 精确版本号 + dist.shasum,和 FriendsOfPHP/security-advisories 数据库条目匹配。
-
composer.json改了但没跑composer install→lock没更新,audit 不会发现潜在风险 - 手动拷贝
vendor/或 git clone 进来 →lock缺失或shasum不匹配,audit 主动跳过校验,结果为空 - 包名是 fork 版(如
myorg/guzzle),而数据库只认guzzlehttp/guzzle→ 不匹配,不告警也不提示 - 版本含
-dev、dev-main等标识 → advisories 不收录,audit 主动跳过
CI 流水线里 composer audit 总失败怎么办
默认行为是:只要发现任意一条 advisory(哪怕 5 年前的 low 级条目),就返回非零退出码。这不是 bug,但你不该让它这么跑。
- 生产卡点只关注真正可利用的风险:
composer audit --severity=critical --severity=high --no-dev - 网络不稳定时防卡住:
composer audit --no-interaction --timeout=30 - 结果要供脚本解析:
composer audit --format=json --no-dev | jq '.advisories[] | select(.severity == "critical")'(需提前装jq) -
--ignore=CVE-2023-12345可临时豁免,但必须在代码注释或文档里写明理由
composer audit 没报漏洞 ≠ 安全
它只查 FriendsOfPHP/security-advisories 这个社区维护的数据库,覆盖有限:
- 小众包、私有包、未提交到该库的 CVE,它完全看不见
- 不分析代码调用链,不判断你是否真用到了有漏洞的函数路径
- 不检查 PHP 版本、扩展启用状态、运行时配置(比如 debug 模式是否开启)
- 不扫描
composer.json中未 lock 的依赖,也不管require-dev里的工具链(除非加--dev)
真正要评估风险,得人工看 advisory 描述、复现条件、你的实际用法——audit 只是起点,不是结论。











