composer audit 是唯一官方支持的依赖漏洞扫描命令,但需同时满足 Composer ≥ 2.5.0、experimental.audit 启用、composer.lock 有效且可访问 Packagist 安全数据库四个条件,缺一则静默失败或报错。

composer audit 是当前唯一官方支持的依赖漏洞扫描命令,但它不是“开箱即用”,必须满足四个硬性条件:Composer ≥ 2.5.0、experimental.audit 已启用、composer.lock 存在且有效、能访问 Packagist 安全数据库。缺一不可,否则会静默无输出或报 Command "audit" is not defined。
确认 audit 命令是否真正可用
很多人卡在这一步就以为工具失效,其实是没过准入检查:
- 运行
composer --version—— 必须 ≥2.5.0;若低于此值,执行composer self-update - 运行
composer list | grep audit—— 若无输出,说明实验特性未激活,需运行composer config --global experimental.audit true - 检查
composer.lock是否存在且非空:ls -l composer.lock,若被.gitignore忽略或哈希校验失败,audit会跳过 - 验证网络连通性:
curl -I https://packagist.org,若返回cURL error 7,说明 DNS 或代理阻断了安全数据库请求
为什么 audit 扫不出已知 CVE?常见数据源陷阱
不是漏报,而是数据链断裂。audit 只比对 composer.lock 中记录的精确版本与 FriendsOfPHP/security-advisories 数据库,以下情况必然不命中:
-
composer.lock过期 —— 比如改了composer.json但没跑composer install,audit 仍查旧版本 - 用了国内镜像源(如阿里云、腾讯云)—— 它们不同步
/security-advisories接口,临时切回官方源:composer config --global repo.packagist.org https://packagist.org - 包版本含
dev-前缀(如dev-main)—— audit 主动跳过,因安全库不收录开发分支 - 私有包未在
repositories中声明,或其元数据缺失security-advisories字段 —— 默认不参与扫描
让 audit 输出真正可落地的结果
默认输出信息密度低、干扰多,上线前或 CI 中应收紧范围:
- 只关注真实可利用风险:
composer audit --severity=critical --severity=high --no-dev - 结构化输出供脚本解析:
composer audit --format=json --no-dev,再用jq '.advisories[] | select(.severity == "critical")'提取关键项 - 忽略已知可控漏洞(慎用):
composer audit --ignore=CVE-2023-12345,但必须在代码注释中写明豁免理由和临时缓解措施 - CI 卡点防误伤:
composer audit --no-interaction --timeout=30,避免网络抖动导致构建挂起
发现漏洞后,别急着 update
audit 只报告,不判断上下文。真实影响取决于三件事:
- 查看漏洞详情中的
affected versions范围,确认composer.lock中安装的版本确实在其中 - 检查该包是否被实际调用 ——
require-dev里的测试工具类,即使有CVE-2026-xxxxx也无运行时风险 - 优先用
composer update vendor/package --with-dependencies升级到已修复版本;若无法升级,考虑禁用相关功能路径,而非硬加补丁 - 更新后务必重新运行
composer audit并提交新的composer.lock—— 否则下次扫描还是旧结果
最容易被忽略的是:audit 不扫描 vendor/ 目录,也不读 composer.json 的版本约束。它只认 composer.lock 里那一行精确的 "version": "x.y.z"。删掉 vendor 重装没用,锁文件不更新,审计结果就不会变。











