根本原因是Composer audit硬编码直连https://packagist.org/advisories,私有镜像未同步该端点;需配代理或手动配置advisories源,且私有包须在composer.json中严格补全security-advisories元数据。

composer audit 在私有镜像中为什么总报“Could not fetch security advisories”
根本原因是私有镜像(尤其是自建 Packagist 或代理镜像)未同步 FriendsOfPHP/security-advisories 数据库,或拦截/丢弃了 https://packagist.org/advisories 这个专属端点请求。
Composer 2.5+ 的 audit 命令不走镜像配置的主源(repo.packagist.org),而是**硬编码直连官方 advisories 接口**。哪怕你已用 composer config --global repos.packagist composer https://mirrors.example.com 切换镜像,audit 仍会绕过它去访问原始地址。
- 企业内网环境必须显式配置代理:
export HTTP_PROXY=http://proxy.internal:8080,且确保该代理能转发GET https://packagist.org/advisories - 若完全离线,可临时替换为本地镜像提供的 advisories 端点(需镜像服务支持):
composer config --global repos.advisories composer https://mirrors.example.com/advisories - 验证是否生效:运行
composer audit --force --no-dev,观察是否仍报错;成功时会显示 “Fetched X advisories”
私有包和 fork 包怎么让 composer audit 扫到漏洞
audit 默认跳过所有非 Packagist 官方注册的包,包括 myorg/laravel-fork、path 类型本地依赖、以及通过 repositories.type: package 声明的私有包——不是 bug,是设计限制。
要让它参与扫描,必须在 composer.json 中为每个私有包**手动补全 security-advisories 元数据字段**,格式需严格匹配 FriendsOfPHP 数据库结构:
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
{
"name": "myorg/guzzle",
"type": "package",
"version": "7.5.1",
"dist": { ... },
"security-advisories": {
"CVE-2023-1234": {
"title": "XXL injection in request body",
"link": "https://github.com/myorg/guzzle/security/advisories/GHSA-abc1-2def-3ghi",
"cve": "CVE-2023-1234",
"severity": "high",
"fixed": "7.5.2"
}
}
}
- 字段名必须是
security-advisories(复数、小写、短横线),不能是advisories或security -
fixed值必须是精确语义化版本号,如"7.5.2",不能是"^7.5.2"或"dev-main" - CI 中需确保
composer install成功后,该元数据才被写入composer.lock;否则audit读不到
CI 流水线里怎么安全地集成 audit + 合规性检查
不能只跑一次 composer audit 就算完事。生产级 CI 必须组合三件事:锁文件可信性校验、开发依赖覆盖、许可协议兜底。
- 前置校验:
composer validate --strict检查composer.json是否符合平台约束(如 PHP 版本、扩展),避免audit通过但部署失败 - 必须加
--with-dev:composer audit --with-dev --severity=critical,high --format=json,否则 PHPUnit、PHPStan 等工具链漏洞直接漏掉 - 许可协议不能只靠
composer show:它不查传递依赖,也不处理"SEE LICENSE IN LICENSE"这类值;推荐用jq -r '.packages[] | select(.license == null or .license == "proprietary" or .license == "unlicensed") | .name' composer.lock提前筛出高风险项 - 退出码逻辑要重写:默认遇到任意 high/critical 就失败,但 CI 应允许人工确认;建议用
jq '.advisories | map(select(.severity == "critical" or .severity == "high")) | length == 0'做判断依据
为什么升级到 Composer 2.9.6 还是扫不出 CVE-2023-41277 这类 Laravel 漏洞
不是版本问题,是数据库同步延迟。FriendsOfPHP/security-advisories 的更新存在小时级 lag,尤其对 Laravel、Symfony 等高频发布框架,新 CVE 录入可能比 Packagist 包更新慢 6–24 小时。
更关键的是:audit 只认 composer.lock 里记录的**安装哈希值**。如果 lock 文件里存的是 "hash": "abcd1234",但 FriendsOfPHP 数据库里该 CVE 关联的是 "hash": "abcd1235"(即 patch 版本微调了构建产物),audit 就不会命中。
- 强制刷新缓存:
composer audit --force强制重拉 advisories 数据,而非用本地缓存 - 交叉验证:
composer outdated --direct --minor-only查看是否有已知修复版本可用,再比对composer audit --fixed输出的fixed字段 - 别依赖单次扫描:把
composer audit加入每日定时任务,而不是仅在 PR 时跑一次

















