Composer 不主动监控 composer.lock,仅在 install/update 时校验;“lock file is not up to date” 是防止环境不一致的第一道防线;composer audit 需 ≥2.5.0 且启用 experimental.audit 才生效,默认不扫 require-dev;所有 lock 变更必须经命令生成并提交,CI 应校验其是否已提交。

Composer 本身不监控 composer.lock 文件变化,也不会在文件被 Git 修改、手动编辑或同步异常时主动预警——它只在你运行 composer install 或 composer update 时被动校验。所谓“监控预警”,实际是靠组合命令 + 明确触发时机 + CI 集成来实现的。
为什么 composer install 报 “lock file is not up to date” 就是第一道安全防线
这不是报错,是 Composer 在拦你:当前 composer.json 已变,但 composer.lock 还是旧的,环境一致性已断裂。此时若强行绕过(比如用 --no-lock),可能装出和生产/队友完全不同的依赖组合——哪怕只是 monolog/monolog 从 2.9.1 变成 2.10.0,也可能引入未测试过的 CVE。
- 常见诱因:Git 合并时只拉了别人的
composer.json,漏掉对应的composer.lock;CI 流水线先git checkout再composer install,但分支 lock 不对齐 - 正确响应:立刻执行
composer update --lock(不是update!),它只重写 lock,不升级包、不碰vendor/ - 必须跟一句
git add composer.lock && git commit -m "sync lock after json change",否则下一个人立刻复现
composer audit 是唯一能主动发现已知漏洞的命令,但有硬性前提
它不扫描代码,也不猜版本,只比对 composer.lock 里记录的**精确版本号 + 完整哈希** 和 FriendsOfPHP/security-advisories 数据库里的条目。低于 Composer 2.5.0?命令直接不存在。
- 确认可用:运行
composer --version(必须 ≥ 2.5.0)+composer config --global experimental.audit(必须返回true) - 默认跳过
require-dev中的包,如phpunit/phpunit有反序列化漏洞也不会报——加--with-dev才扫 - 私有包、fork 包、
dev-main版本一律不查,且不提示“已跳过”,容易误以为扫全了 - CI 中建议用
composer audit --severity=high,critical,避免 low 级漏洞导致构建失败,又不错过真正要命的问题
如何让 composer.lock 变更本身变成可审计事件
Git 提交 composer.lock 的那一刻,才是依赖变更的真实时间点。但光靠 Git 日志不够,得绑定语义化动作:
- 禁止手动编辑
composer.lock:它含content-hash、子依赖快照、dist shasum,改错一个逗号就导致composer install报Invalid argument supplied for foreach() - 所有 lock 变更必须来自
composer update --lock或composer update,并在 commit message 里写明动因,例如:"chore(composer): update lock after adding spatie/laravel-ray --with-dev" - CI 流水线中,在
composer install前加一步:git diff --quiet composer.lock || (echo "ERROR: composer.lock changed but not committed" && exit 1),防漏提交
真正难的不是命令怎么敲,而是让团队所有人理解:一个没提交的 composer.lock,和一段没测过的 SQL,危险程度是一样的——它不会立刻崩,但会在最意想不到的节点,把整个依赖树拖进未知状态。


















