composer audit 命令不存在或无输出,根本原因是 composer 版本低于 2.5.0 或未启用 experimental.audit 配置;它仅比对 composer.lock 中的精确版本与 friendsofphp 安全数据库,不扫描 vendor、代码、私有包或 dev 分支,且结果受限于数据库覆盖范围。

composer audit 命令为什么不存在或没输出
不是插件没装、镜像配错,而是 Composer 版本低于 2.5.0,或者实验特性未启用。直接运行 composer audit 报 Command "audit" is not defined 或静默无输出,基本就这三件事没做对:
- 运行
composer --version:必须是2.5.0或更高;2.4.x及更低版本压根不带这个命令 - 运行
composer list | grep audit:没输出 = 命令未注册,即使版本达标也无效 - 执行
composer config --global experimental.audit true:该配置写入全局auth.json,缺了它,audit不触发扫描逻辑
某些定制版 composer.phar(比如锁定 PHP 7.2 的旧 Docker 镜像)可能根本没编译审计模块,self-update 会失败,只能换官方完整版。
composer audit 扫的是 vendor 还是 composer.lock
它只读 composer.lock,完全不看 vendor/ 目录里的文件内容。锁文件里记录的精确包名 + 精确版本号 + 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) - 想忽略已知可控漏洞(慎用):
composer audit --ignore=CVE-2023-12345
注意:--severity 不支持 medium 或 low 卡点,它们不会中断命令执行。
audit 查不到 CVE 就代表安全吗
完全不代表。它只比对 FriendsOfPHP/security-advisories 数据库里的条目,这个库主要覆盖 Symfony、Laravel、Drupal 等主流生态确认并标记的漏洞,大量小众包、未提交的 CVE、或私有仓库包根本不在收录范围内。
- 查不到 CVE ≠ 没漏洞,很可能是数据库没覆盖 —— 别依赖它发现全部问题
- 它不分析代码、不查 NVD、不检测运行时环境或配置错误,纯靠版本号硬匹配
- 务实做法:把
composer audit当基础防线,CI 中再叠加一次snyk test --file=composer.lock --severity-threshold=high,两者互补 - 私有包必须在
composer.json的repositories中显式声明,且元数据需支持security-advisories字段,否则默认不参与扫描
真正容易被忽略的点是:audit 的“无输出”常被当成“安全”,其实大概率是锁文件不准、数据库未覆盖、或私有源没配对 —— 它不报错,只沉默跳过。











