自建composer私有仓库本身不安全,必须主动配置三道防线:强制https并禁用目录浏览、启用gpg签名并验证元数据、ci中正确注入且校验composer_auth;未设防线则内网仓库形同裸奔。

自建 Composer 私有仓库本身不提供安全,它只是把攻击面从公网搬进了你的内网——而多数团队连最基本的三道防线都没设。
私有仓库服务端必须强制 HTTPS 并禁用目录浏览
HTTP 明文传输凭证、包元数据、签名文件,等于把钥匙挂在门把手上;Nginx/Apache 开启 autoindex on 会让 /packages/ 目录裸奔,curl https://repo.your-company.com/packages/ 就能下载所有源码 ZIP。
- 确保所有响应走 HTTPS:Nginx 配置中删除
autoindex on,加location / { try_files $uri =404; } - 禁止直接访问包文件路径:对
/packages/.*\.zip$和/packages\.json$加鉴权或 403 - 不要用
http://URL 声明仓库,哪怕在内网——Composer 2.5+ 会静默降级并跳过签名验证
必须启用 GPG 签名并验证元数据完整性
没签名的 packages.json 是一张可随意涂改的购物清单:攻击者中间人劫持后替换其中某个包的 ZIP 地址,composer install 就会拉下恶意版本。Satis 构建时漏掉 --sign,等于没锁保险柜。
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
- 构建命令必须带
php bin/satis build satis.json web/ --sign,生成packages.json.asc - 客户端要开启验证:
composer config -g repo.packagist.org.allow_ssl_downgrade false(防止降级到 HTTP) - 确认生效:
composer show --security输出中需含Signature verification: enabled - 私有仓库签名密钥必须离线保管,不能和构建机共存
CI/CD 中注入 COMPOSER_AUTH 的格式与校验不能出错
COMPOSER_AUTH 是个 JSON 字符串,但 Composer 对格式极其敏感:多一个空格、少一个引号、换行符残留,都会导致认证失效且无明确报错——构建卡在“找不到包”,排查两小时才发现是 JSON 拼错了。
- 必须是单行、无换行、键名全小写:
COMPOSER_AUTH='{"http-basic":{"packages.your-company.com":{"username":"ci","password":"xxx"}}}' - 禁止手写拼接,用
jq生成:echo '{"http-basic": {"'"$REPO_HOST"'": {"username": "'"$CI_USER"'", "password": "'"$CI_TOKEN"'"}}}' | jq -c - CI 第一步加校验:
composer config --global --list | grep -q "http-basic",失败则exit 1 - 绝对不要在
composer.json里注释掉凭证——Git 历史里一搜就出来
仓库优先级配置不当会绕过私有签名验证
如果私有仓库没放在 repositories 数组最前面,或者没禁用 packagist.org fallback,Composer 可能先去官方源找同名包,完全跳过你签了名的私有版本——尤其当私有包版本号较低时,require 语句没锁死版本,就会自动选高版本“公共包”。
- 私有仓库声明必须置于
repositories顶部,且显式加"packagist.org": false(注意不是"packagist": false) - 验证是否生效:
composer install -vvv日志里不能出现任何packagist.org请求 - 若需混合使用,用
only字段限定私有仓库只提供acme/*类包,避免覆盖公共生态
最常被忽略的一点:签名只保护元数据和包文件本身,不保护包内部代码逻辑。如果你的私有包依赖了未签名的第三方包,或者包里自带 install 脚本,那签名再严也没用——得靠 --no-scripts 和 --no-dev 配合静态分析兜底。










