composer默认复用本地缓存zip文件且跳过哈希校验,导致被篡改缓存可静默安装恶意包;需通过sha256sum比对缓存zip与composer.lock中dist.shasum,或使用composer_experimental=1 composer verify-checksums --strict强制验证。

Composer 不会自动检测或拒绝已被篡改的本地缓存包——它默认复用 ~/.composer/cache/files/ 中的 ZIP 文件,跳过重新下载,也跳过哈希比对。这是设计使然,不是 bug;但若缓存被污染,composer install 会静默安装恶意内容。
为什么 composer install 不报错,却装了被篡改的包
缓存复用是 Composer 的性能优化逻辑,但也是安全盲区:
- 一旦
~/.composer/cache/files/vendor/package/name/version.zip被手动替换或注入恶意代码,后续composer install直接解压该文件,不校验、不告警 - 即使
composer.lock中dist.shasum正确,校验只发生在“首次下载时”,缓存命中即绕过 - 镜像源同步滞后或被劫持后提供错误 ZIP,若已进缓存,后续所有 install 都复用这个坏包
-
--prefer-dist(默认)走缓存,--prefer-source则完全不看dist.shasum,二者都可能跳过校验
如何确认缓存是否已被篡改
不能靠感觉,得查文件实际哈希与 lock 是否一致:
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
- 先定位缓存路径:
composer config --global cache-dir - 找一个已安装包的缓存 ZIP:
find $(composer config --global cache-dir) -name "package-name-*.zip" | head -1 - 算它的 SHA-256:
sha256sum /path/to/cached.zip - 打开
composer.lock,搜索该包的"dist": { "shasum": "..." }字段,比对是否完全一致(64 字符,大小写敏感) - 若不一致,说明缓存文件已被替换或损坏;若一致,也不能排除“攻击者提前替换了缓存+同步改了 lock”这种组合操作
强制跳过缓存并触发完整校验的实操命令
临时禁用缓存,让 Composer 回到“下载→校验→解压”原始流程,是最直接的验证方式:
- 清空当前项目缓存影响范围:
composer clear-cache(注意:这清的是全局缓存,非仅当前项目) - 删掉 vendor:
rm -rf vendor/ - 禁用缓存并强制校验:
COMPOSER_CACHE_DIR=/dev/null composer install --no-cache --verbose - 观察输出:必须看到
Downloading https://api.packagist.org/.../package.zip和Verifying archive checksum,且无跳过提示 - 若中途报
Signature mismatch或Hash does not match,说明缓存曾被篡改,或镜像未同步原始包
verify-checksums --strict 是唯一能回检 vendor 的手段
它不依赖网络,只读取已安装文件和 composer.lock,但必须显式启用实验模式且带 --strict:
- 确认版本 ≥ 2.5:
composer --version - 运行:
COMPOSER_EXPERIMENTAL=1 composer verify-checksums --strict - 它会遍历
vendor/下每个包(跳过.git/、tests/、vendor/bin/),计算整体 SHA-256,并与composer.lock中对应dist.shasum比对 - 不加
--strict时,不匹配只警告、返回码仍是 0;加了才真正失败退出,适合 CI 流水线断言 - 注意:它不校验
autoload.php是否被手动修改——那属于运行时篡改,verify-checksums无感
缓存被篡改后最危险的点在于:它不留下日志、不中断流程、不触发任何钩子。你只能靠主动验证,而不是等报错。别把 clear-cache 当成安全措施,它只是重置;真正要做的,是在 CI/CD 中固定加入 COMPOSER_EXPERIMENTAL=1 composer verify-checksums --strict,并确保 composer.lock 提交进 Git、禁止被覆盖。










