composer config -g repo.packagist 会放大劫持风险,因其彻底替换官方源,导致 Composer 跳过 packagist.org 提供的 signature 字段校验;国内镜像不生成也不透传该签名,一旦缓存污染或同步延迟,便静默安装篡改包。

为什么composer config -g repo.packagist会放大劫持风险
执行composer config -g repo.packagist https://mirrors.aliyun.com/composer/不是“加速”,而是彻底替换官方源,导致 Composer 完全跳过 signature 字段校验——该字段只由 packagist.org 在 HTTPS 响应头中提供。国内镜像(阿里云、腾讯云、清华源)既不生成也不透传 signature,一旦缓存被污染或同步延迟,composer install 就会静默下载篡改过的 ZIP 包。
典型现象包括:
- CI 构建通过,但线上运行时触发未声明的
post-install-cmd -
vendor/中文件哈希与composer.lock不匹配,却无报错 - 抓包看到
packages.json来自镜像,但dist.zip实际从非预期域名下载
如何启用真正防中间人攻击的 HTTPS 镜像配置
关键不是“换源”,而是保留 packagist.org 的语义和签名锚点能力:元数据走镜像,包文件仍由官方 CDN 提供并校验。
- 先关闭危险源替换:
composer config -g repo.packagist false - 启用元数据代理(仅影响
packages.json等元数据请求):composer config -g repos.packagist.type composer,再执行composer config -g repos.packagist.url https://mirrors.aliyun.com/composer/ - 强制开启签名验证:
composer config -g security.signature true - 确保 HTTPS 强制启用:
composer config -g secure-http true(默认已开,禁用即高危)
验证是否生效:composer diagnose 输出中必须同时出现 secure-http: OK 和 signature verification: OK。
composer.lock 是离线防劫持的最后一道闸
只要 composer.lock 完整且提交进 Git,composer install 就完全不发网络请求——它只从 ~/.composer/cache/files 读取 ZIP 并比对 dist.shasum。DNS 劫持、中间人、镜像宕机,全被挡在门外。
-
composer.lock中每个包的dist.shasum必须存在且为 64 字符(SHA-256),否则校验逻辑不会触发 - 手动改一个
shasum值为"0000"后运行composer install,必须中止报错;否则说明 lock 文件未被读取,或用了--ignore-platform-reqs等绕过选项 - CI 流水线建议加
composer install --no-scripts --no-plugins,观察是否出现Hash does not match报错
为什么对象存储多版本控制(MVC)不能防篡改
对象存储(如 OSS、S3)开启多版本后,每次上传同名文件都会保留旧版本,但它不校验内容真实性:上传恶意 packages.json 或篡改后的 dist.zip,MVC 会安静存下,不报错也不拦截。
MVC 唯一有效场景是事后回滚:
- 发现线上
vendor/autoload.php被注入代码 → 查该包安装时间 → 对象存储中找对应dist.zip的历史版本 → 提取未被篡改的 SHA-256 值 -
composer verify-checksums --strict失败 → 对比当前composer.lock中的shasum和 MVC 各版本哈希值,定位哪次上传出问题
真正的防线永远在 composer.lock 的非空 shasum、security.signature 是否启用,以及每次 install 是否真的执行了哈希比对——MVC 只是备份,不是开关。











