verify-checksums --strict 是唯一能真实校验 vendor 文件哈希的命令,需启用 COMPOSER_EXPERIMENTAL=1 且必须加 --strict;它逐包扫描 vendor 目录(跳过 .git、tests/ 等),归并文件字节流计算 SHA256 并与 composer.lock 中 dist.sha256 比对,但不校验 autoload_*.php 等生成文件。

composer verify-checksums --strict 是唯一能校验 vendor 文件真实哈希的命令
它不是默认启用的功能,必须显式开启实验模式:COMPOSER_EXPERIMENTAL=1 composer verify-checksums --strict。不加 --strict 时即使发现哈希不匹配也只警告并返回 0,CI 流水线会误判为成功;不设环境变量则该命令根本不可见。
该命令逐包扫描 vendor/ 目录(跳过 .git、tests/ 等非发布路径),归并所有文件字节流后计算 SHA256,并与 composer.lock 中对应包的 dist.sha256 字段比对。
- 跳过
"type": "path"的包,或没有dist.sha256字段的旧私有包(不会报错,但容易漏检) - 不校验
vendor/composer/autoload_*.php这类生成文件 -
vendor/autoload.php虽是引导文件,但会被扫描到,且无对应哈希记录,手动修改它会导致校验失败
为什么 composer install 成功后 verify-checksums 却失败
composer install 只在校验刚下载的 ZIP/TAR 包(解压前)是否匹配 composer.lock 中的 dist.sha256;一旦解压落地,就不再回头检查。
verify-checksums 是真打开 vendor/ 目录,递归读所有文件再算一次 SHA256。两者校验时机和对象完全不同。
- CI 中用了
--prefer-source:走 git clone,完全绕过哈希校验,verify-checksums会跳过该包(因无dist.sha256) - 本地缓存被污染后重装,却复用了坏包:
install阶段没触发校验(缓存命中),但verify-checksums会暴露磁盘上已存在的篡改 - 镜像源替换了 dist 包但未同步原始哈希:
install阶段“匹配”,verify-checksums却会爆 mismatch
校验失败后如何定位具体篡改文件
verify-checksums --strict 报 mismatch 时不会指明哪个文件出问题,需手动提取包哈希并逐文件比对:
- 从
composer.lock中找到对应包的dist.sha256值 - 进入
vendor/vendor-name/package-name/目录 - 用
find . -type f ! -name '.*' -print0 | xargs -0 cat | shasum -a 256计算归并哈希 - 若不一致,再用
find . -type f ! -name '.*' -exec shasum -a 256 {} \;逐个排查异常文件
生产部署前必须补上的三道防线
仅靠 verify-checksums 不足以保障安全,关键文件完全游离在校验体系外:
- 将
vendor/设为只读(防止运行时篡改) - 部署后断言
vendor/autoload.php内容未被注入——可预先保存其 SHA256,在启动脚本中校验 - 不可依赖
composer validate或--dry-run,它们不读vendor目录,也不计算任何文件哈希
最危险的是 autoload.php 和 autoload_static.php 这类引导文件:它们由 Composer 生成,不参与任何哈希校验,一旦被注入恶意代码,整个应用入口即被劫持。


















