首页 >  科技周边 >  业界新闻

npm 新增发布前恶意软件扫描:CI 如何处理 contentPolicy、DISCLOSURE 与 2FA

来源:17golang原创

时间:2026-08-16 17:36:05 108浏览 收藏

之前搭建 npm 发布流水线,很多团队都默认「命令返回成功」就等于「下游马上可以安装」。这个判断从 2026 年 7 月开始不再稳妥:npm 会在新包对外可安装前做自动恶意软件扫描,包可能正常可用,也可能暂存人工复核或被拦截;即使发布接口已经返回,安装验收仍要多等一个状态确认。

要点速览
  • 普通包发布后通常会有几分钟的可用性延迟,高峰或包体较大时可能更久。
  • 双用途安全能力要在 package.json 声明 contentPolicy,并在根目录放纯文本 DISCLOSURE。
  • 双用途包必须通过可信发布、交互式双因素认证或 staged publishing 等强制 2FA 的路径发布。
  • CI 要把“发布成功”和“可安装成功”拆成两个检查点,不能用固定秒数代替状态判断。

npm 这次变化到底改了哪一个时间点

变化不在 npm publish 的基本语法,而在“版本何时可以被安装”。官方说明新版本会先进入扫描流程,根据结果走正常发布、人工复核或拦截三条路径。常见延迟约为 5 分钟,繁忙时可能达到 15 分钟以上;这只是当前行为,不是服务承诺。

因此,流水线里至少要区分下面三个结果:

检查点能说明什么不能说明什么
发布命令返回凭证和发布请求被接受新版本已经可安装
dist-tag 可查看版本标签已经登记tarball 已能被所有安装请求取到
干净环境安装下游目前可以解析并取得版本以后每次发布都不会进入复核

npm 发布扫描链路:发布命令进入扫描后分流到可安装、人工复核或拦截状态

CI 不要把发布成功当成安装成功

最小改造是把发布任务和可用性验收拆开。发布任务保存版本号与 dist-tag,验收任务在短暂退避后,从一个没有 npm 缓存的环境读取该版本。读不到时先记录为“扫描中”,不要立刻把整条发布标为失败。

npm publish --provenance
printf 'published=%s\n' "$npm_package_name@$npm_package_version"

# 在独立验收任务中执行,避免复用构建机缓存
npm view "$npm_package_name@$npm_package_version" version --registry=https://registry.npmjs.org
npm pack "$npm_package_name@$npm_package_version" --dry-run --registry=https://registry.npmjs.org

这里的关键不是多加一个命令,而是让重试有边界:例如第 1、3、7、15 分钟各检查一次,超过窗口就转人工复核。若脚本把一次“暂不可安装”当成永久失败,就会误触发重复发布;同一个版本也不应该靠改 tag 来绕过扫描。

带安全能力的包要准备 contentPolicy 和 DISCLOSURE

有些合法工具具备网络诊断、凭证处理、系统观察或自动化控制能力,自动扫描可能把它们视作双用途内容。npm 新增的声明路径是:在 package.json 放入 contentPolicy 字段,并在包根目录提供名为 DISCLOSURE 的纯文本文件。

{
  "name": "team-audit-kit",
  "version": "2.4.0",
  "contentPolicy": "dual-use"
}

DISCLOSURE 不应写成宣传文案,而要说明两件事:这项能力具体做什么,以及维护者准备在哪种合法场景中使用它。声明不会自动保证放行,平台仍可能继续扫描并由 Trust & Safety 团队逐案判断。

npm 双用途包的声明关系:contentPolicy、DISCLOSURE 与强制 2FA 发布共同进入复核链路

双用途包的发布通道和后续版本有两个硬边界

第一,发布必须走强制双因素认证的方式,例如 trusted publishing(OIDC)、带双因素认证的交互式会话,或 staged publishing。仅凭一个可绕过 2FA 的细粒度令牌直接发布,不符合这项要求。

第二,声明是持续性的。某个版本带有 contentPolicyDISCLOSURE 后,后续版本不能把它们删掉,否则发布会被拒绝。建议把这两个文件放进发布前的清单,和版本号、许可证、打包文件一起做差异检查。

  • 包内确认 package.json 的声明仍存在。
  • 确认 DISCLOSURE 在 tarball 根目录,而不是只存在于源码仓库。
  • 确认 CI 使用的发布身份真的启用了 2FA 强制策略。
  • 确认发布后等待窗口不会触发第二次相同版本发布。

把一次发布改成可复查的验收记录

每次发布至少保留包名、版本、dist-tag、发布时间、扫描等待开始时间、首次可安装时间和最终状态。若进入人工复核,还要保存平台通知和申诉材料,不要只在日志里留下一行“publish ok”。

这项更新对普通包的直接动作很小:给安装检查增加退避和超时;对双用途包则要把元数据、说明文件和强制 2FA 一并纳入版本流程。这样遇到延迟时,团队知道是在等待扫描,遇到拦截时,也能拿出一份完整而克制的用途说明。

常见问题

发布命令成功后可以立刻让用户安装吗?

不建议。先经过短暂等待,再从干净环境验证版本确实可取得;发布成功只代表请求被接受。

双用途声明能保证包一定上线吗?

不能。contentPolicy 和 DISCLOSURE 只提供必要的上下文,平台仍会自动扫描,必要时还会人工复核。

后续版本可以删除 DISCLOSURE 吗?

不可以。已经声明过双用途内容的包,后续版本应持续保留字段和根目录文件。

安全更新也要等待三天吗?

不要把 npm 发布扫描和 Dependabot 的版本更新冷却混为一谈。后者的默认冷却针对版本更新 PR,安全更新仍按安全规则及时打开。

最后的检查清单

把 npm 发布任务改成“两段式”:先记录发布请求,再等待并验证可安装状态。普通包关注延迟、重试和重复发布;双用途包再增加 contentPolicy、DISCLOSURE、强制 2FA 与持续声明四项检查。验收记录完整后,npm 的扫描流程就从一次不可控的等待,变成了发布系统里可观察、可回溯的一步。

声明:本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>