content-hash 是 composer.json 中与依赖解析相关字段的 SHA-256 哈希,不校验注释、空行、autoload、scripts、extra、dist.shasum、source.reference 等无关内容。

content-hash 是什么,它不校验哪些内容
content-hash 是 composer.lock 文件顶部的一个字符串字段,由 Composer 自动生成。它**不是对整个 lock 文件做哈希**,而是对 composer.json 中**与依赖解析直接相关的内容**做 SHA-256 哈希:包括 require、require-dev、conflict、replace、provide、minimum-stability、prefer-stable 和 platform 字段的结构化 JSON 表示(已排序、无空格)。
这意味着以下修改**不会触发 content-hash 变更**:
-
composer.json中注释、空行、字段顺序调整 -
autoload、scripts、extra等不影响依赖图的字段变更 - 手动编辑
composer.lock中某包的dist.shasum或source.reference
它如何参与 install/update 的安全检查
当运行 composer install 时,Composer 会重新计算当前 composer.json 的 content-hash,并与 composer.lock 里记录的值比对。如果不一致,说明 composer.json 已被修改但 lock 文件未更新——此时 Composer 会中止执行并报错:
Changed current directory to /path/to/project Installing dependencies from lock file (including require-dev) Verifying lock file contents can be installed on current platform. Your lock file does not contain a compatible set of packages. Please run composer update.
这个机制防止的是「开发环境改了依赖声明却忘了 composer update,然后把过期 lock 文件提交到 CI 或部署」这类人为疏漏。但它不提供防篡改保护:攻击者若能同时修改 composer.json 和 composer.lock,就能绕过该检查。
为什么不能靠它防供应链攻击
content-hash 完全不涉及包内容本身。它不管:
-
dist.url指向的 ZIP 是否被镜像劫持(如 DNS 污染或恶意 packagist 镜像) -
dist.shasum字段是否被篡改(该字段仅在install时校验下载包完整性,但 lock 文件本身可被随意编辑) -
source.type为git时,source.reference对应的 commit 是否真实存在或已被覆盖(force-push)
换句话说:content-hash 是“声明一致性”检查,不是“来源可信性”或“内容真实性”检查。它的作用边界非常明确——只确保你安装的依赖组合,确实是你当时 composer update 所生成的那个组合。
真正起保护作用的是 dist.shasum 和 vendor/bin/composer verify-lock
如果你关心 lock 文件是否被篡改,应该关注:
-
dist.shasum:每个包的压缩包 SHA-256,在install时自动校验下载内容。这是实际防篡改的第一道防线 -
composer verify-lock(Composer 2.2+):它会重新解析composer.json,执行完整依赖求解,并比对结果与composer.lock中的packages列表是否完全一致(包括版本、约束、源信息)。这比content-hash严格得多,但耗时也显著增加 - 使用
--lock强制模式(如composer update --lock)可避免意外覆盖 lock 文件
所以别把 content-hash 当作安全锁;它只是个快速一致性快照。真要验证 lock 文件可信,得靠 verify-lock + 完整的 dist.shasum 校验链 + 可信的 Composer 配置源(比如固定 packagist.org 域名、禁用非 HTTPS 镜像)。










