GSD 包合法性门禁(Package Legitimacy Gate):在 Agent 驱动开发中拦截 slopsquat 供应链攻击
导读
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 常常需要自主推荐并安装第三方依赖。但大模型的训练知识天然存在两个致命短板:
- 知识陈旧:训练数据滞后 6~18 个月,模型可能推荐一个已经改名、下架或早已被放弃的包;
- 幻觉命名:模型会“自信地”编造一个看起来合理的包名,而注册表上恰好存在同名的高仿包(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 的代码块中必须包含带
--json的slopcheck install调用,且必须用command -v或which做可用性守卫; - 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 acheckpoint:human-verifytask.
这与研究阶段贯穿始终的“声明溯源”规则相呼应: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 vianpmjs.com/package,pypi.org/project, orcrates.io/crates.[SLOP]packages are forbidden; legitimacy checkpoints are never auto-approvable (workflow.auto_advanceignored). KeepT-{phase}-SCin<threat_model>.
从中可以提炼出 planner 侧的三条硬约束:
- 每个
[SUS]/[ASSUMED]包都被转化为一个<task type="checkpoint:human-verify" gate="blocking-human">前置任务,并给出对应注册表官方 URL 作为人工核验入口; [SLOP]包被明令禁止,合法性 checkpoint 永远不可自动审批——即使工作流配置了workflow.auto_advance也会被忽略,gate="blocking-human"明确宣示这一点;- 供应链威胁必须持续登记在威胁模型里:PLAN.md 模板的
<threat_model>STRIDE 表中保留T-{phase}-SC(supply-chain)行,处置方式为mitigate,确保该风险在计划层面被显式跟踪而非淡出视野。
配套测试 tests/package-legitimacy-gate.test.cjs(gsd-planner.md — checkpoint gate 与 supply-chain row in threat_model template 两组用例)会逐字断言上述措辞的存在,例如“package verification checkpoint includes registry URL guidance”。
六、执行防线:executor RULE 3 的 auto-fix 例外
防线的最后一段在 gsd-executor.md 的 RULE 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 acheckpoint:human-verifytask — 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 install或Package 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]打标需在同一附近窗口内出现; - planner:
checkpoint:human-verify必须同时关联[ASSUMED]与[SUS];必须使用gate="blocking-human"与“never auto-approvable”措辞;checkpoint 指导必须给出npmjs.com/package、pypi.org/project、crates.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: Security、pr: 3215,正文一句话概括用户可见变更。这一机制由 .changeset/README.md 与 scripts/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-DD 按 type: 分组合并进版本发布说明(该修复随 v1.42.x 系列发布说明分发,见 docs/RELEASE-v1.42.0-rc.1.md 与 docs/RELEASE-v1.42.3.md)。
十、小结:一次把“安全语义”写进 Agent 指令的范本
回看本次 Security changeset,包合法性门禁的精髓在于三点设计取舍:
- 层级化而非一刀切:
[SLOP]删除、[SUS]打标保留、[ASSUMED]降级人工、[OK]放行——风险等级对应不同处置力度,而非单纯“禁用外部包”; - 优雅降级而非硬失败:工具缺失时全量降级
[ASSUMED],让每次安装都经过人工确认,把“可能漏检”转化为“必然人工把关”; - 自动化的边界意识:连 executor 的 auto mode 也明确为 package-legitimacy checkpoint 关闭自动批准通道,并以
gate="blocking-human"结构性排除 auto-approval,同时全面用command -v守卫取代npx --yes自动下载。
对于任何构建 Agent 化研发流水线、需要让 LLM 自主推荐并安装依赖的团队,这道“三环互锁 + 结构契约测试锁死指令文本”的门禁设计,都是一份可以直接借鉴的供应链安全范式。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0627
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00