私有仓库本身不提供交付安全,真正决定外包代码是否安全交付的是元数据签名、传输加密和客户端验证三者全部做对。

私有仓库本身不提供交付安全,它只是把代码物理隔离了——真正决定外包代码是否安全交付的,是元数据签名、传输加密和客户端验证这三件事有没有全部做对。
为什么直接给外包方配个私有仓库地址就等于裸奔
很多团队以为只要把 satis.json 里加个 "type": "vcs" 指向外包 Git 地址,再配个 HTTP Basic 认证就算安全了。实际不是:
- 如果外包仓库用的是 HTTPS 公共地址(比如
https://github.com/outsource-team/payment-sdk),那composer install时 Composer 会直接走公网拉取,中间人可替换 ZIP 包或篡改packages.json - 如果外包方自己搭了个简易 Composer 服务但没启用 GPG 签名,他们 push 的任意版本都会被你无条件信任——2025 年某金融客户就被植入了伪造的
vendor/xxx/payment-gateway,因为packages.json被篡改后引导安装了恶意 tag - 外包交付的
composer.json里若硬编码了"url": "git@github.com:...",而你本地没配 SSH key,Composer 会静默 fallback 到 HTTPS,且默认不校验证书
必须强制开启的客户端元数据验证
哪怕私有仓库服务端做了所有加固,客户端不验证签名,一切归零。关键命令只有一条,但必须在所有开发机和 CI 环境执行:
composer config -g repo.packagist.org.allow_ssl_downgrade false
同时确保:
- PHP 的
openssl扩展已启用(php -m | grep openssl) -
composer.json中禁用不安全协议:"config": {"secure-http": true} - 如果外包包用了自签名证书,不要设
"allow_self_signed": true,而是把 CA 证书导入系统信任链
交付物里必须包含且不可绕过的三个文件
外包交付的压缩包或 Git tag 中,以下三项缺一不可,否则无法验证完整性:
-
composer.lock:必须含有效content-hash和每个包的dist.shasum,且不能由composer update生成(应由外包方在 clean 环境下运行composer install --no-dev后提交) -
satis.json或等效仓库配置:明确声明外包包来源为"type": "composer",而非"vcs";URL 必须是带认证路径的私有域名(如https://packages.outsource-company.com),不能是原始 Git 地址 - GPG 签名文件(如
packages.json.sig):Satis 构建时需加--sign参数生成,客户端用gpg --verify packages.json.sig packages.json可人工抽检
CI 流水线里最容易漏掉的认证注入检查
外包交付后,你的 CI 要能自动识别并拒绝无效凭证。别信 COMPOSER_AUTH 环境变量存在就万事大吉:
- 必须校验 JSON 格式合法性:
echo "$COMPOSER_AUTH" | jq empty >/dev/null || exit 1 - 必须确认目标仓库域名出现在配置中:
echo "$COMPOSER_AUTH" | jq -r '.["http-basic"] | keys[]' | grep -q 'packages\.outsource-company\.com' - 禁止在
composer.json里出现任何http-basic字段注释——Git 历史里残留的注释可能被误解析,导致凭证泄露
最危险的盲区是:你以为外包交付的是“代码”,其实你真正上线的是他们控制的元数据源。签名、HTTPS、客户端验证,三者断一,交付即失效。











