composer audit扫不出漏洞是因为它仅比对composer.lock中已安装包的精确版本与FriendsOfPHP安全数据库,不分析代码、不跟踪调用链、不覆盖私有包或未安装依赖,且默认跳过require-dev;需满足Composer≥2.5.0、启用experimental.audit、lock文件完整三条件才有效。

composer audit 为什么扫不出你担心的漏洞
它根本不是深度扫描工具,只是把 composer.lock 里已安装包的 name + version 拿去比对 FriendsOfPHP/security-advisories 这个静态 JSON 列表。不分析代码、不跟踪调用链、不检查私有 fork、不覆盖未安装依赖,连 require-dev 都默认跳过。
常见误判场景:
- 看到
No security vulnerabilities found就以为安全——实际可能是包没被收录、版本带dev-main、或用了自定义仓库名(如mycorp/guzzle) - 报出
CVE-2023-46805,但你的项目根本没调用涉及 SSRF 的那个方法——audit 不做上下文判断 - CI 流水线里只跑
composer audit,没加--dev,结果phpunit/phpunit里的反序列化漏洞直接漏掉
如何让 composer audit 真正起作用
必须满足三个硬条件:Composer ≥ 2.5.0、全局启用实验特性、composer.lock 已存在且完整。
执行顺序不能错:
-
composer self-update --2(确保是 2.5+,老版本连 Packagist 新 API 都不认) -
composer config --global experimental.audit true(写入auth.json,不是项目级) -
composer install或composer update(audit 只读vendor/和installed.json,空 lock = 空结果) -
composer audit --dev --severity=high --severity=critical --no-interaction(CI 必备参数)
注意:--full 参数会强制检查所有已安装包(含 dev-only),但不会帮你发现 platform 不兼容问题——那是 composer validate --strict 的事。
工作流任务拆解与模型编排技能。使用场景:(1) 收到复杂工作任务需要拆解为可执行步骤,(2) 需要为不同步骤选择最合适的模型,(3) 需要跟踪工作流进度和模型使用情况,(4) 长时间任务卡住需要问题诊断和解决方案。
私有包、fork 包、path 依赖怎么审计
默认全跳过。audit 只认 Packagist 官方命名空间(如 guzzlehttp/guzzle),对 acme/guzzle-fork 或 "type": "path" 类型零响应。
可行补救方式:
- 在
composer.json中为私有包显式声明"type": "package",并手动提供"advisories"字段(需按 Symfony 格式) - 用
composer show --format=json --locked提取所有包元数据,再调用内部漏洞库 API 做语义化比对(如^7.4.0是否落在"versions": [" 范围内) - 对关键私有组件,定期人工查其 Git 仓库的
SECURITY.md、issue 标签、最近 commit 时间和 maintainer 活跃度
别信 composer audit 对私有包返回的 “No advisories found” —— 它只是没查,不是没有。
替代方案比 audit 更可靠
真正做深度依赖审计,得组合外部工具:
-
local-php-security-checker /path/to/project:本地运行,不依赖网络,能覆盖部分 NVD 数据 -
snyk test --file=composer.lock:对接 Snyk 漏洞库,支持私有 registry 配置和忽略策略 - 自己封装脚本:用
composer show --locked --format=json输出,喂给 OSV.dev API(支持语义化版本匹配和影响路径推导)
audit 的本质是快速兜底,不是深度审计。它漏报不可怕,可怕的是把它当唯一依据——尤其当你项目里混着 fork 包、自建镜像、或 PHP 版本锁死在 8.1 这种老环境时,platform 兼容性、扩展缺失、甚至 ext-xml 编译选项差异,都可能比 CVE 更早击穿上线流程。

















