CI中composer audit总失败或漏报,是因为它需满足三条件:Composer≥2.5.0、全局启用experimental.audit、存在有效composer.lock;且必须加--no-dev、--severity=critical,high、--no-interaction参数,并确保先执行composer install再审计。

CI 中直接跑 composer audit 会失败或漏报,不是命令写错了,而是它默认行为根本不适合流水线。
为什么 CI 里 composer audit 总是失败或没输出
它不是“一装就能用”的命令,CI 镜像里大概率缺三样东西:
-
composer --version小于 2.5.0 —— 命令根本不存在,报Command "audit" is not defined - 全局配置
experimental.audit没启用 —— 即使版本够,也静默无输出 -
composer.lock被.gitignore忽略、损坏、或哈希不匹配 —— audit 主动跳过,不报错也不提醒
CI 中必须加的三个参数:--no-dev、--severity、--no-interaction
默认行为是:只要发现任意一条 advisory(包括 5 年前的 low 级条目),就返回非零退出码。这在 CI 里等于“永远失败”。真正要加的是:
-
--no-dev:跳过require-dev里的包,避免 PHPUnit、phpstan 这类工具链漏洞干扰生产发布 -
--severity=critical --severity=high:只让高危和严重级中断构建;medium和low不参与退出码判定 -
--no-interaction:禁用交互式提示,防止卡住;配合--timeout=30更稳妥,防网络抖动超时
CI 流水线里 audit 的执行顺序不能错
audit 读的是 composer.lock,不是 vendor/,也不是 composer.json。所以必须保证:
- 先执行
composer install --no-interaction(确保 lock 文件被正确解析、vendor 生成完整) - 再运行
composer audit --no-dev --severity=critical,high --no-interaction - 如果项目用了私有仓库,
composer.json的repositories必须显式声明security-advisories元数据,否则 fork 包、内部包一律不扫
audit 扫不出漏洞 ≠ 没漏洞,只是它能力边界在这里
它只比对 composer.lock 里记录的**精确版本号 + dist.shasum** 和 FriendsOfPHP/security-advisories 数据库条目。这意味着:
- 你手动改过
composer.lock或复制了 vendor?哈希不匹配 → audit 跳过整包,不报、不提示 - 用了
dev-main、dev-feature/x或私有包名?advisories 不收录 → 直接忽略 - 漏洞刚披露还没同步进数据库?audit 看不见,哪怕 CVE 编号已公开
- 它不分析调用链、不查 PHP 配置是否触发、不覆盖 NVD 全量 CVE —— 只是第一道过滤网


















