首页
/ GSD 包合法性门禁(Package Legitimacy Gate):在 Agent 驱动开发中拦截 slopsquat 供应链攻击

GSD 包合法性门禁(Package Legitimacy Gate):在 Agent 驱动开发中拦截 slopsquat 供应链攻击

2026-09-07 22:19:06作者:翟江哲Frasier

导读

get-shit-done(GSD)是一套面向 Claude Code 的轻量级 meta-prompting 与 spec-driven 开发系统。在其发布周期中,.changeset/graceful-otters-wave.md 记录了一项 Security 类型的安全加固:GSD 引入了“包合法性门禁”,要求所有研究员推荐的外部包在写入 RESEARCH.md 之前先经过 slopcheck 校验,并以前置 Agent(researcher → planner → executor)三环嵌套的指令约束,封堵 AI 幻觉出恶意/仿冒包名的供应链风险。读完本文,你将理解 GSD 如何定义 [SLOP]/[SUS]/[ASSUMED]/[VERIFIED] 分级处置模型、如何通过 checkpoint:human-verify 强制人工介入,以及为什么 GSD 全面废弃了 npx --yes 自动下载模式。

一、为什么需要一道“包合法性门禁”

LLM 驱动开发的场景里,Agent 常常需要自主推荐并安装第三方依赖。但大模型的训练知识天然存在两个致命短板:

  1. 知识陈旧:训练数据滞后 6~18 个月,模型可能推荐一个已经改名、下架或早已被放弃的包;
  2. 幻觉命名:模型会“自信地”编造一个看起来合理的包名,而注册表上恰好存在同名的高仿包(slopsquat)——仿冒包往往携带恶意 install 脚本,等待不知情的 pip install/npm install/cargo add 触发。

更麻烦的是,传统“查一下包是否存在”的校验方式完全无效:正如 gsd-phase-researcher.md 第 33 行所强调的——注册表存在性本身并不能带来 [VERIFIED] 状态,因为一个 slopsquatted 仿冒包同样能通过 npm view

因此本次 Security changeset 在 GSD 三个关键 Agent 的指令层同时落下一套互锁约束,形成从“包名进入研究文档”到“包被安装”的整条供应链防线。

二、门禁总体设计:researcher → planner → executor 三环接力

包合法性门禁并非单一工具,而是一条贯穿三个 Agent 的约束链,对应三份核心 Agent 指令文件:

环节 Agent 文件 职责
上游处置 gsd-phase-researcher.md 用 slopcheck 校验每个待推荐包;[SLOP] 直接删除,[SUS]/[ASSUMED] 打标并写入审计表
计划兜底 gsd-planner.md 为每个 [SUS]/[ASSUMED] 包插入 checkpoint:human-verify 强制人工确认,禁止自动放行
执行拦截 gsd-executor.md RULE 3 明确将包管理器安装排除在 auto-fix 范围之外,安装失败一律转人工核查

这三份指令的文本契约由专门的回归测试 tests/package-legitimacy-gate.test.cjs 锁定(对应 issue #2827)。该测试逐字校验三个文件中必须存在的关键指令,例如:

  • researcher 的代码块中必须包含带 --jsonslopcheck install 调用,且必须用 command -vwhich 做可用性守卫;
  • researcher 的 RESEARCH.md 模板必须包含带指定列(Package / Registry / Age / Downloads / slopcheck / Disposition)的 Package Legitimacy Audit 表格;
  • planner 的包合法性 checkpoint 必须使用 gate="blocking-human",并声明“never auto-approvable”;
  • executor 的 RULE 3 段落必须出现“排除包管理器安装”的措辞。

三、上游防线:研究员侧的四步校验协议

<package_legitimacy_protocol> 定义在 gsd-phase-researcher.md 第 265~322 行,凡是会安装外部包的 phase,都必须先跑完这套流程再产出 ## Package Legitimacy Audit 审计段。

Step 1 — 尽力安装 slopcheck

门禁不因工具缺失而硬失败,采用 best-effort 安装策略:

pip install slopcheck --break-system-packages 2>/dev/null || pip install slopcheck 2>/dev/null || true

Step 2 — 运行合法性检查(带 command -v 守卫)

if command -v slopcheck &>/dev/null; then
  slopcheck install <pkg1> <pkg2> ... --json
else
  echo "slopcheck not available — marking all packages [ASSUMED]"
fi

注意 --json 是硬性要求(测试中专门断言了该 flag),便于 Agent 结构化解析裁决结果。

结果分级处置:

  • [SLOP](slopsquatted):幻觉或危险性过高的新包——必须整体移除,不得出现在任何 RESEARCH.md 推荐中,仅在审计表 Disposition: REMOVED 一栏留痕;
  • [SUS](suspicious):新发布、下载量极低、或没有源码仓库的包——保留但内联打标`pkg-name` [WARNING: slopcheck flagged as suspicious — verify before using.]
  • [OK](clean):校验干净,正常放行。

优雅降级(Graceful degradation)原则是本次设计的关键安全语义:slopcheck 装不上或跑不动时,把每一个推荐包标记为 [ASSUMED](而不是 [VERIFIED]),让 planner 逐个在安装前生成 checkpoint:human-verify。文档明确评价道:"This is strictly safer than the current baseline — never a hard failure."——宁可在缺失工具时全量降级为人工确认,也不愿把存在性误判成安全。

Step 3 — 生态特定的注册表校验

按 phase 主语言运行对应命令,防止“跨生态串台”:

# Node.js / JavaScript phases
npm view <pkg> version

# Python phases
pip index versions <pkg>

# Rust phases
cargo search <pkg>

指令文件特别警告:跨生态混淆(一个包名在 npm 上存在、但在 PyPI 上不存在却被误判为 Python 包)是有记录可查的幻觉向量(约 9% 概率),因此必须去正确的生态注册表核实。

Step 4 — Node.js 阶段的 postinstall 脚本排查

npm view <pkg> scripts.postinstall 2>/dev/null

凡 postinstall 脚本引用了网络调用或指向项目目录之外的文件系统路径,即为高危信号——即使 slopcheck 评定为 [OK],也要升级标记为 [SUS]

四、研究产物的固化:Package Legitimacy Audit 审计表

校验结果必须固化到 RESEARCH.md 的 ## Package Legitimacy Audit 段(模板同样内嵌在 gsd-phase-researcher.md 第 379~392 行),格式如下:

Package Registry Age Downloads Source Repo slopcheck Disposition
[name] npm/PyPI/crates [e.g., 8 yrs] [e.g., 50M/wk] [github.com/org/repo 或 "none"] [OK] Approved
[name] npm [e.g., 3 days] [e.g., 0] none [SLOP] REMOVED
[name] npm [e.g., 2 mo] [e.g., 800/wk] [github.com/…] [SUS] Flagged — planner must add checkpoint

审计段尾部还需要两份显式清单:

Packages removed due to slopcheck [SLOP] verdict: [list, or "none"] Packages flagged as suspicious [SUS]: [list — planner inserts checkpoint:human-verify before each install] If slopcheck was unavailable at research time, all packages above are tagged [ASSUMED] and the planner must gate each install behind a checkpoint:human-verify task.

这与研究阶段贯穿始终的“声明溯源”规则相呼应:researcher 在顶层定义了三级 provenance tag——[VERIFIED: npm registry](官方文档或 Context7 确认且通过 slopcheck)、[CITED: docs.example.com/page](引官方文档)、[ASSUMED](仅凭训练知识)。包名溯源规则进一步规定:凡经 WebSearch、训练数据等非权威渠道发现的包名,即使 npm view 确认其存在于注册表,也必须打 [ASSUMED],绝不可自动升格为 [VERIFIED]

五、计划防线:planner 如何把每个风险包变成人工闸门

研究输出进入规划阶段后,gsd-planner.md 承担“把关”职责,其核心规则是:

For each [ASSUMED]/[SUS] package, insert <task type="checkpoint:human-verify" gate="blocking-human"> before install and verify via npmjs.com/package, pypi.org/project, or crates.io/crates. [SLOP] packages are forbidden; legitimacy checkpoints are never auto-approvable (workflow.auto_advance ignored). Keep T-{phase}-SC in <threat_model>.

从中可以提炼出 planner 侧的三条硬约束:

  1. 每个 [SUS]/[ASSUMED] 包都被转化为一个 <task type="checkpoint:human-verify" gate="blocking-human"> 前置任务,并给出对应注册表官方 URL 作为人工核验入口;
  2. [SLOP] 包被明令禁止,合法性 checkpoint 永远不可自动审批——即使工作流配置了 workflow.auto_advance 也会被忽略,gate="blocking-human" 明确宣示这一点;
  3. 供应链威胁必须持续登记在威胁模型里:PLAN.md 模板的 <threat_model> STRIDE 表中保留 T-{phase}-SC(supply-chain)行,处置方式为 mitigate,确保该风险在计划层面被显式跟踪而非淡出视野。

配套测试 tests/package-legitimacy-gate.test.cjsgsd-planner.md — checkpoint gatesupply-chain row in threat_model template 两组用例)会逐字断言上述措辞的存在,例如“package verification checkpoint includes registry URL guidance”。

六、执行防线:executor RULE 3 的 auto-fix 例外

防线的最后一段在 gsd-executor.mdRULE 3: Auto-fix blocking issues 中。该规则专门追加了一段排除声明(第 180~184 行附近):

EXCLUDED from RULE 3 — package manager installs: Running npm install <pkg>, pip install <pkg>, cargo add <pkg>, or any equivalent package-manager install command is NOT auto-fixable. If a referenced package fails to install or cannot be found: ... Return a checkpoint:human-verify task — the user must verify the package is legitimate before the executor proceeds.

由此得到 executor 侧的行为契约:

  • 包管理器安装失败不是可自动修复项——executor 不得自行“换个版本/换个源”蒙混过关,而是构造 <task type="checkpoint:human-verify" gate="blocking-human"> 把决定权交还用户;
  • 包合法性 checkpoint 一律使用 gate="blocking-human",从语义上彻底排除被自动批准的可能;
  • 即便处于 auto mode,executor 也会自动批准除 package-legitimacy checkpoints 之外的人工确认点——一旦 what-built 出现 Package verification required before installPackage install failed — human verification required 之类的意图标记,就必须 STOP 并返回 checkpoint_return_format 等待显式人工确认。

七、斩断 npx --yes 自动下载:以 command -v 守卫取代

本次 Security changeset 的另一半内容,是把散落在三个 Agent 文件中的 npx --yes 自动下载模式全面替换为 command -v 存在性守卫。其动机在 researcher 的文档查询段落中写得非常直白:"Do NOT use npx --yes to auto-download ctx7 — this silently executes unverified packages from the registry."——npx --yes 会在不提示的情况下从注册表拉取并执行任意包,恰好是供应链攻击的理想入口。

替换后的标准模式如下(以 Context7 CLI 回退为例,来自 gsd-phase-researcher.md 第 50~54 行):

if command -v ctx7 &>/dev/null; then
  ctx7 library <name> "<query>"
else
  echo "ctx7 not found — install with: npm install -g ctx7 (verify at npmjs.com/package/ctx7 first)"
fi

测试文件对三个 Agent 文件逐一断言“代码块内不得出现 npx --yes”(no npx --yes auto-download 用例组),并对 ctx7 回退路径单独校验 command -v ctx7 守卫存在,从机制上防止该反模式回潮。

八、机制保障:结构契约测试如何锁死安全语义

所有上述规则之所以可信,是因为它们不只是文档建议,而是被结构契约测试逐字锁死的强制指令。打开 tests/package-legitimacy-gate.test.cjs 可以看到它以测试即规范的方式覆盖:

  • researcher:slopcheck 必须以 fenced code block + --json + command -v/which 守卫的方式出现;模板含 Package Legitimacy Audit 节及 6 个必备列;同时文档 [SLOP]/[SUS]/[OK] 三态;给出 pip index versions/cargo search 生态命令;禁用 npx --yes;WebSearch 来源包与 [ASSUMED] 打标需在同一附近窗口内出现;
  • plannercheckpoint:human-verify 必须同时关联 [ASSUMED][SUS];必须使用 gate="blocking-human" 与“never auto-approvable”措辞;checkpoint 指导必须给出 npmjs.com/packagepypi.org/projectcrates.io/crates 的 URL 示例;<threat_model> 中必须存在 T-{phase}-SC 供应链行且处置为 mitigate
  • executor:RULE 3 段落必须提及 npm install/pip install/cargo add 并明确其“被排除/不可自动修复”;安装失败措辞与 checkpoint:human-verify 必须同框出现;auto mode 段落必须声明对 package-legitimacy checkpoint 不做自动批准。

这类“指令即契约”的测试(仓库中同属此类结构性回归的还有 tests/lint-docs-required.test.cjs 等)确保未来任何对 Agent 指令的改写,若削弱了防仿冒供应链的三环防线,都会在 CI 中立即失败。

九、发布与变更管理

该变更以 per-PR changelog 片段的形式落地在 .changeset/graceful-otters-wave.md:frontmatter 声明 type: Securitypr: 3215,正文一句话概括用户可见变更。这一机制由 .changeset/README.mdscripts/changeset/new.cjs 支持——每次 PR 通过 node scripts/changeset/new.cjs --type Security --pr 3215 --body "..." 生成随机三个单词命名的片段文件,避免多个 PR 同时编辑 CHANGELOG.md 的合并冲突;发布时再由 node scripts/changeset/cli.cjs render --version vX.Y.Z --date YYYY-MM-DDtype: 分组合并进版本发布说明(该修复随 v1.42.x 系列发布说明分发,见 docs/RELEASE-v1.42.0-rc.1.mddocs/RELEASE-v1.42.3.md)。

十、小结:一次把“安全语义”写进 Agent 指令的范本

回看本次 Security changeset,包合法性门禁的精髓在于三点设计取舍:

  1. 层级化而非一刀切[SLOP] 删除、[SUS] 打标保留、[ASSUMED] 降级人工、[OK] 放行——风险等级对应不同处置力度,而非单纯“禁用外部包”;
  2. 优雅降级而非硬失败:工具缺失时全量降级 [ASSUMED],让每次安装都经过人工确认,把“可能漏检”转化为“必然人工把关”;
  3. 自动化的边界意识:连 executor 的 auto mode 也明确为 package-legitimacy checkpoint 关闭自动批准通道,并以 gate="blocking-human" 结构性排除 auto-approval,同时全面用 command -v 守卫取代 npx --yes 自动下载。

对于任何构建 Agent 化研发流水线、需要让 LLM 自主推荐并安装依赖的团队,这道“三环互锁 + 结构契约测试锁死指令文本”的门禁设计,都是一份可以直接借鉴的供应链安全范式。

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.13 K
2.75 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
857
1.35 K
docsdocs
暂无描述
Markdown
897
5.8 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
529
593
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
915
1.83 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.58 K
1.01 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.35 K
1.46 K
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
1.01 K
515
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
547
388