敏感凭证绝不会、也不该出现在 composer install 的终端输出里——若出现,说明已被明文硬编码进 auth.json、composer.json 或命令行参数;正确做法是使用 Composer 2.0+ 支持的环境变量插值(如 "${GITLAB_TOKEN}"),配合系统级环境变量注入,确保凭证不落地、不回显、不泄露。

敏感凭证绝不会、也不该出现在 composer install 的终端输出里——如果看到了,说明它已经被硬编码进配置文件或命令行参数中,这本身就是泄露。
为什么 composer install 会输出敏感信息?
根本原因只有一种:凭证被明文写进了 auth.json、composer.json 或通过 --http-basic 参数传入。Composer 本身不“隐藏”凭证,它只是原样回显你给它的值(比如在调试模式下或失败时打印 URL)。
- 常见错误:在
composer.json的config段写"http-basic": {"repo.example.com": {"username": "user", "password": "secret123"}}—— 提交即泄露 - 更隐蔽的错误:CI 脚本里写
composer config http-basic.repo.example.com user $TOKEN,而$TOKEN未被 mask,日志直接暴露 -
auth.json若含https://user:pass@形式 URL,composer install在 fetch dist 时可能把完整 URL 打印到 stderr(尤其网络失败时)
用环境变量插值替代明文密码(Composer 2.0+)
这是唯一被官方支持、且能真正避免输出敏感值的方式:让 Composer 在运行时从系统环境读取,而不是把密码塞进 JSON 文件里。
-
auth.json必须放在COMPOSER_HOME目录下(Linux/macOS 是~/.composer/auth.json,Windows 是%APPDATA%\Composer\auth.json),不能放项目根目录 - 内容写成:
{ "http-basic": { "gitlab.com": { "username": "gitlab-ci-token", "password": "${GITLAB_TOKEN}" } } } - 确保环境变量已设置:
GITLAB_TOKEN=xxx(CI 中用 secrets 注入,本地开发用export GITLAB_TOKEN=...) - 验证是否生效:
composer config --list | grep http-basic不会显示密码,只会显示占位符或空值
禁止在 composer.json 的 scripts 或 extra 里拼接带密钥的命令
哪怕只在脚本里写 "deploy": "curl -H 'Authorization: Bearer ${API_KEY}' ...",只要 composer run deploy 执行,密钥就可能出现在 CI 日志、开发者终端或进程列表中。
- 正确做法:把密钥提取到外部脚本,由 shell 环境变量注入,例如
"deploy": "deploy.sh",而deploy.sh用curl -H "Authorization: Bearer $API_KEY" - CI 中必须启用日志 masking:GitHub Actions 需声明
secrets: [API_KEY];GitLab CI 要设variables: { API_KEY: $API_KEY }并开启 masked - 绝对不要用
composer config动态写入含密钥的配置——它会写进auth.json或composer.json,等于二次泄露
检查 composer.lock 是否意外携带凭证
composer.lock 不存密钥,但可能藏间接泄露路径:dist URL 里若含 ?token= 或 user:pass@,就会随文件一起提交。
- 快速扫描:
grep -A2 '"dist":' composer.lock | grep -E '(url|token=|@)' | grep -v '"url": null' - 修复方式:删掉含凭证的 URL,改用
http-basic+ 环境变量方式认证;私有镜像应配置为http-basic类型而非 URL 内嵌 - CI 流水线中加校验步骤:
composer validate --strict虽不查 URL,但能发现异常字段嵌套,提示手工篡改痕迹
最易被忽略的一点:auth.json 文件权限。即使用了环境变量,如果 auth.json 本身权限是 644(世界可读),而里面写了 ${TOKEN} 占位符,攻击者仍可能通过读取该文件推测出变量名并发起针对性攻击。务必设为 600(Linux/macOS)或等效 ACL(Windows)。


















