patch
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
Chinesepatch
补丁生成
Third leg of the static pipeline ( → → ).
Turns a ranked list of verified findings into candidate diffs.
/vuln-scan/triage/patchThe skill never applies a diff to the target repo. Output is inert text
in for a human to review and apply out-of-band — see
. There is no or
flag by design: the capability isn't present, so it can't be
prompt-injected into use.
./PATCHES/docs/patching.md#reviewing-generated-patches--apply--approveInvoke with .
/patch <findings-path> [--repo PATH] [--top N] [--id fNNN] [--model M] [--fresh]Arguments (parse from ):
$ARGUMENTS- findings path (first positional, required): ,
TRIAGE.json, a pipelineVULN-FINDINGS.jsondirectory, or any JSON theresults/<target>/<ts>/ingest table recognizes./triage - : target codebase, read-only (default cwd). Required for static mode; the skill stops if cited files don't resolve under it.
--repo PATH - : patch only the N highest-severity true positives (static mode).
--top N - : patch only the finding with this id.
--id fNNN - : passed through to
--model Min execution-verified mode. Ignored in static mode (subagents inherit the orchestrator's model).vuln-pipeline patch - : ignore
--freshcheckpoint and start over../.patch-state/
Tools. Prefer Read, Glob, Grep, Write, Task. Some sessions do not
provision Glob or Grep; is a permission filter, not a loader.
When they are unavailable, fall back to the read-only Bash commands
whitelisted above: / for search, for enumeration,
// for sniffing, for JSON ingest. Bash is otherwise
permitted only for (state I/O)
and (execution-verified delegate). is NOT
permitted.
allowed-toolsrggreplsheadfilewcjqpython3 .claude/skills/_lib/checkpoint.pyvuln-pipeline patchfindWrite scope. The Write tool may target ONLY paths under and
. Never write into , never , never
, never edit target source. If a step seems to require it, the step is
wrong.
./PATCHES/./.patch-state/--repogit applypatch静态流水线的第三个环节( → → )。
将已排序的已验证漏洞列表转换为候选diff文件。
/vuln-scan/triage/patch本技能绝不会将diff应用到目标仓库。输出内容是目录下的惰性文本,供人工审核后离线应用——详见。设计上没有或参数:该功能不存在,因此无法通过提示注入触发。
./PATCHES/docs/patching.md#reviewing-generated-patches--apply--approve调用方式:。
/patch <findings-path> [--repo PATH] [--top N] [--id fNNN] [--model M] [--fresh]参数(从解析):
$ARGUMENTS- 漏洞路径(第一个位置参数,必填):、
TRIAGE.json、流水线VULN-FINDINGS.json目录,或任何results/<target>/<ts>/流程可识别的JSON文件。/triage - :目标代码库,只读(默认当前目录)。静态模式下必填;若引用文件无法在此路径下解析,技能将终止。
--repo PATH - :仅为前N个最高严重性的真阳性漏洞生成补丁(静态模式)。
--top N - :仅为指定ID的漏洞生成补丁。
--id fNNN - :在执行验证模式下传递给
--model M。静态模式下忽略(子代理继承编排器的模型)。vuln-pipeline patch - :忽略
--fresh检查点,从头开始执行。./.patch-state/
工具:优先使用Read、Glob、Grep、Write、Task。部分会话未提供Glob或Grep;是权限过滤器,而非加载器。当这些工具不可用时,回退到上述白名单中的只读Bash命令:/用于搜索,用于枚举,
//用于探查,用于JSON解析。Bash仅允许用于(状态输入输出)和(执行验证委托)。命令不允许使用。
allowed-toolsrggreplsheadfilewcjqpython3 .claude/skills/_lib/checkpoint.pyvuln-pipeline patchfind写入范围:Write工具仅能写入和路径下的文件。绝不能写入目录,绝不能执行、或编辑目标源代码。若某步骤似乎需要这些操作,则该步骤存在错误。
./PATCHES/./.patch-state/--repogit applypatchCheckpointing (runs before Phase 0 and after every phase)
检查点机制(在第0阶段前和每个阶段后运行)
State persists to so a fresh session resumes
without re-spawning patch or reviewer subagents. All checkpoint I/O goes
through (atomic, JSON-validated).
The Write→ pattern keeps repo-derived bytes out of Bash argv; never
pass payload via heredoc or stdin.
./.patch-state//patchpython3 .claude/skills/_lib/checkpoint.py--fromState files: (single source of truth: ),
, .
progress.json{"status": "running"|"complete", "phase_done": N, "shards_done": [...]}phaseN.json_chunk.tmpStart of run. Bash:
python3 .claude/skills/_lib/checkpoint.py load ./.patch-state- OR
status == "absent", OR"complete"in--fresh→ fresh start. Bash:$ARGUMENTS, proceed to Phase 0.python3 .claude/skills/_lib/checkpoint.py reset ./.patch-state - with
status == "running"→ resume. Readphase_done == N..phase0.jsonin order (and anyphaseN.jsonlisted inshard_*.json), merge into working state, printshards_done, skip to Phase N+1. Do not re-spawn any subagent whose output is already checkpointed.Resuming from checkpoint: Phase N complete
End of every phase N. Write tool → with the
phase's JSON, then Bash:
./.patch-state/_chunk.tmppython3 .claude/skills/_lib/checkpoint.py save ./.patch-state <N> <name> --from ./.patch-state/_chunk.tmpEnd of run. After writing and , Bash:
PATCHES.mdPATCHES.jsonpython3 .claude/skills/_lib/checkpoint.py done ./.patch-state 4状态会持久化到目录,因此新的会话可以恢复执行,无需重新启动补丁或审核子代理。所有检查点输入输出均通过执行(原子操作,JSON验证)。Write→模式可避免仓库衍生字节进入Bash参数;绝不要通过 heredoc 或标准输入传递负载。
./.patch-state//patchpython3 .claude/skills/_lib/checkpoint.py--from状态文件:(唯一可信来源:)、
、。
progress.json{"status": "running"|"complete", "phase_done": N, "shards_done": [...]}phaseN.json_chunk.tmp运行开始:执行Bash命令:
python3 .claude/skills/_lib/checkpoint.py load ./.patch-state- 若或
status == "absent",或"complete"中包含$ARGUMENTS→ 从头开始。执行Bash命令:--fresh, 进入第0阶段。python3 .claude/skills/_lib/checkpoint.py reset ./.patch-state - 若且
status == "running"→ 恢复执行。依次读取phase_done == N..phase0.json(以及phaseN.json中列出的所有shards_done),合并到工作状态,打印shard_*.json,跳至第N+1阶段。不要重新启动任何输出已被检查点保存的子代理。Resuming from checkpoint: Phase N complete
每个阶段N结束:使用Write工具将阶段的JSON写入,然后执行Bash命令:
./.patch-state/_chunk.tmppython3 .claude/skills/_lib/checkpoint.py save ./.patch-state <N> <name> --from ./.patch-state/_chunk.tmp运行结束:写入和后,执行Bash命令:
PATCHES.mdPATCHES.jsonpython3 .claude/skills/_lib/checkpoint.py done ./.patch-state 4Phase 0: Parse arguments and detect mode
第0阶段:解析参数并检测模式
0a. Parse $ARGUMENTS
$ARGUMENTS0a. 解析$ARGUMENTS
$ARGUMENTSExtract findings path (first positional), (default ), ,
, , . If no findings path, stop and ask.
--repo.--top--id--model--fresh提取漏洞路径(第一个位置参数)、(默认)、、
、、。若未提供漏洞路径,终止并询问用户。
--repo.--top--id--model--fresh0b. Detect mode
0b. 检测模式
Inspect the findings path:
- execution-verified mode when the path is a directory containing
OR
reports/manifest.jsonlORfound_bugs.jsonl(pipeline output). The findings have PoC bytes + ASAN traces + reproduction commands; the pipeline's verification ladder applies.run_*/result.json - static mode otherwise: ,
TRIAGE.json, generic finding JSON, or markdown. No PoC; the oracle is a fresh-context reviewer.VULN-FINDINGS.json
Record in working state. The two modes share Phase 1 ingest then fork
at Phase 2.
modeCheckpoint: Write tool → :
Then Bash:
./.patch-state/_chunk.tmp{"phase": 0, "mode": "exec"|"static", "args": {repo, top, id, model, findings_path}}python3 .claude/skills/_lib/checkpoint.py save ./.patch-state 0 mode --from ./.patch-state/_chunk.tmp检查漏洞路径:
- 执行验证模式:路径为包含
或
reports/manifest.jsonl或found_bugs.jsonl的目录(流水线输出)。漏洞包含PoC字节、ASAN跟踪信息和复现命令;流水线的验证流程将生效。run_*/result.json - 静态模式:其他情况,包括、
TRIAGE.json、通用漏洞JSON或Markdown文件。无PoC;验证依赖全新上下文的审核员。VULN-FINDINGS.json
在工作状态中记录。两种模式共享第1阶段的解析流程,在第2阶段分叉。
mode检查点:使用Write工具将以下内容写入:
然后执行Bash命令:
./.patch-state/_chunk.tmp{"phase": 0, "mode": "exec"|"static", "args": {repo, top, id, model, findings_path}}python3 .claude/skills/_lib/checkpoint.py save ./.patch-state 0 mode --from ./.patch-state/_chunk.tmpPhase 1: Ingest and normalize
第1阶段:解析与标准化
Same input contract as Phase 1. Normalize every input format to a
flat of dicts. Pull what's present; never guess what's absent.
/triagefindings[]与第1阶段的输入规则一致。将所有输入格式标准化为扁平的字典数组。提取已有字段;绝不猜测缺失字段。
/triagefindings[]1a. Recognized containers (priority order)
1a. 可识别的输入容器(优先级顺序)
- — read
TRIAGE.json. Filter to.findings[]. This is the canonical input: already verified, deduped, ranked, owner-tagged.verdict == "true_positive" - — read
VULN-FINDINGS.json. Unverified; print.findings[]and continue.Warning: VULN-FINDINGS.json is unverified scanner output. Consider /triage first. - Pipeline results directory — one finding per . Map
reports/bug_NN/→report.json,description→crash.crash_type, ASAN top-frame →category/file. Recordlinefor thebug_id = NNdelegate flag.--bug N - Generic with a top-level list or a
*.json/findings/results/issuesarray.vulnerabilities
- — 读取
TRIAGE.json。过滤出.findings[]的条目。这是标准输入:已验证、去重、排序、标记所有者。verdict == "true_positive" - — 读取
VULN-FINDINGS.json。未验证;打印.findings[]并继续执行。Warning: VULN-FINDINGS.json is unverified scanner output. Consider /triage first. - 流水线结果目录 — 每个对应一个漏洞。 将
reports/bug_NN/映射为report.json,description映射为crash.crash_type, ASAN顶层栈帧映射为category/file。记录line用于bug_id = NN委托参数。--bug N - 通用文件,包含顶层列表或
*.json/findings/results/issues数组。vulnerabilities
1b. Field aliases (canonical ← also-accept)
1b. 字段别名(规范字段 ← 兼容字段)
| Canonical | Also accept |
|---|---|
| |
| |
| |
| |
| |
| |
| |
| |
Attach (, , ... in ingest order; preserve existing ids from
TRIAGE.json) and (relative path of the file it came from).
idf001f002source| 规范字段 | 兼容字段 |
|---|---|
| |
| |
| |
| |
| |
| |
| |
| |
添加(按解析顺序为、...;保留TRIAGE.json中的已有ID)和(来源文件的相对路径)。
idf001f002source1c. Filter and order
1c. 过滤与排序
- If : keep only that finding.
--id fNNN - If (static mode): sort by
--top NHIGH > MEDIUM > LOW thenseveritydesc, keep the first N.confidence - Drop findings with no (cannot patch what cannot be located). Record them as
filewith reasonskipped."no source location"
- 若指定:仅保留该漏洞。
--id fNNN - 若指定(静态模式):按
--top NHIGH > MEDIUM > LOW排序,再按severity降序排序,保留前N个。confidence - 丢弃无字段的漏洞(无法定位的漏洞无法修补)。将这些漏洞记录为
file,原因是skipped。"no source location"
1d. Locate the target codebase (static mode)
1d. 定位目标代码库(静态模式)
Resolve . For the first 5 findings with a , check the path
resolves under repo (try as-given, then with common prefixes stripped). If
none resolve, stop: tell the user the cited files aren't reachable and
suggest a value.
--repofile--repoCheckpoint: Write tool → :
Then Bash:
./.patch-state/_chunk.tmp{"phase": 1, "mode": ..., "findings": [...], "skipped": [...], "repo": ...}python3 .claude/skills/_lib/checkpoint.py save ./.patch-state 1 ingest --from ./.patch-state/_chunk.tmp解析路径。对前5个有字段的漏洞,检查路径是否在仓库下可解析(先尝试原路径,再尝试去除常见前缀)。若均无法解析,终止:告知用户引用文件无法访问,并建议指定值。
--repofile--repo检查点:使用Write工具将以下内容写入:
然后执行Bash命令:
./.patch-state/_chunk.tmp{"phase": 1, "mode": ..., "findings": [...], "skipped": [...], "repo": ...}python3 .claude/skills/_lib/checkpoint.py save ./.patch-state 1 ingest --from ./.patch-state/_chunk.tmpPhase 2: Generate patches
第2阶段:生成补丁
Forks on .
mode根据分叉执行。
mode2A. Execution-verified mode — delegate to the pipeline
2A. 执行验证模式 — 委托给流水线
The pipeline already implements the build → reproduce → regress → re-attack
ladder with executable oracles. Do not reimplement it.
For each finding (or once for the whole directory if no /
filter), Bash:
--id--topvuln-pipeline patch <findings_path> --model <--model arg> [--bug <bug_id>]The pipeline writes itself. After it returns, Read each
and copy + into working state. Set
when , else
.
<findings_path>/reports/bug_NN/{patch.diff, patch_result.json}patch_result.jsonverdictrationaleverified: "ladder_passed"verdict.passed == trueverified: "ladder_failed"If the CLI exits non-zero (no , missing target config), record
the stderr as the finding's and continue with remaining findings.
build_commanderrorSkip Phase 3 (the ladder is the verifier). Proceed to Phase 4.
Checkpoint per finding: Write tool → =
, then Bash:
.
After all findings, write the consolidated phase payload to then:
./.patch-state/_chunk.tmp{"id": ..., "verified": ..., "verdict": ..., "diff_path": ...}python3 .claude/skills/_lib/checkpoint.py shard ./.patch-state <id> --from ./.patch-state/_chunk.tmp_chunk.tmppython3 .claude/skills/_lib/checkpoint.py save ./.patch-state 2 generate --from ./.patch-state/_chunk.tmp流水线已实现构建→复现→回归→重攻击的验证流程,包含可执行验证器。不要重新实现该流程。
对每个漏洞(若未指定/过滤,则对整个目录执行一次),执行Bash命令:
--id--topvuln-pipeline patch <findings_path> --model <--model arg> [--bug <bug_id>]流水线会自行将补丁写入。执行完成后,读取每个并将 + 复制到工作状态。当时设置,否则设置。
<findings_path>/reports/bug_NN/{patch.diff, patch_result.json}patch_result.jsonverdictrationaleverdict.passed == trueverified: "ladder_passed"verified: "ladder_failed"若CLI执行非零退出(无、缺少目标配置),将stderr记录为漏洞的并继续处理剩余漏洞。
build_commanderror跳过第3阶段(流水线流程已完成验证)。进入第4阶段。
每个漏洞的检查点:使用Write工具将以下内容写入 =
,然后执行Bash命令:
。所有漏洞处理完成后,将合并后的阶段负载写入,然后执行:
./.patch-state/_chunk.tmp{"id": ..., "verified": ..., "verdict": ..., "diff_path": ...}python3 .claude/skills/_lib/checkpoint.py shard ./.patch-state <id> --from ./.patch-state/_chunk.tmp_chunk.tmppython3 .claude/skills/_lib/checkpoint.py save ./.patch-state 2 generate --from ./.patch-state/_chunk.tmp2B. Static mode — one patch subagent per finding
2B. 静态模式 — 每个漏洞对应一个补丁子代理
One Task per finding, all in a SINGLE assistant message for parallel
execution. . Never set
— you need the diff text, not an async handle.
subagent_type: "general-purpose"run_in_backgroundEach subagent has read-only access to . It cannot modify the target;
it emits the diff as text in its response. The orchestrator writes that text
to .
--repoPATCHES/bug_NN/patch.diff每个漏洞对应一个Task,所有Task在同一条助手消息中并行执行。。绝不要设置
——需要diff文本,而非异步句柄。
subagent_type: "general-purpose"run_in_background每个子代理对拥有只读访问权限。它无法修改目标代码;仅能在响应中输出diff文本。编排器会将该文本写入。
--repoPATCHES/bug_NN/patch.diffPatch subagent prompt (assemble once, reuse per finding)
补丁子代理提示词(组装一次,每个漏洞复用)
You are conducting authorized security research as part of a defensive
assessment. Your task: write a candidate fix for ONE verified vulnerability
finding in a codebase you have read-only access to.
You may use Read, Glob, and Grep ONLY on paths inside {REPO_PATH}. You may
NOT build, run, install, edit files on disk, or reach the network. You will
emit the fix as a unified diff in your final response; you will NOT apply it.
────────────────────────────────────────────────────────────────────────
FINDING:
id: {id}
file: {file}
line: {line}
category: {category}
severity: {severity}
title: {title}
description:
{description}
recommendation:
{recommendation or "(none provided)"}
────────────────────────────────────────────────────────────────────────
PROCEDURE:
1. READ THE CODE. Open {file} at line {line} and the surrounding function.
Understand what the code does — do not trust the finding's description as
the only source.
2. ROOT CAUSE FIRST. Trace backward from the cited sink to where the bad
value or missing check originates. The fix usually belongs there, not at
the line the scanner flagged. Name the root-cause location (file:line).
3. VARIANT HUNT. Grep for sibling call sites with the same pattern. Your fix
should cover all of them, or your rationale should say why not.
4. MINIMAL DIFF. Smallest change that fixes the root cause. No refactoring,
no drive-by cleanup, no reformatting, no comment-only changes. Match the
surrounding code's style (brace placement, naming, error handling).
5. ADVERSARIAL SELF-CHECK. Re-read your diff as an attacker. Name one input
variation that would reach the same bad state without tripping your
change. If you can name one, your fix is at the wrong layer — go back to
step 2.
6. REGRESSION TEST. As part of the diff, add ONE test case that fails before
your change and passes after — placed wherever the project keeps its
tests (look for test_*/, *_test.*, tests/, spec/). If no test directory
exists, omit the test and say so in <test_note>.
────────────────────────────────────────────────────────────────────────
OUTPUT — your final response MUST contain exactly these tags. Emit the diff
verbatim between the markers; do NOT wrap it in ``` fences.
<patch_diff>
--- a/path/to/file
+++ b/path/to/file
@@ ... @@
context line
-removed line
+added line
</patch_diff>
<rationale>what changed and why, mechanically — file:line of root cause,
what the change enforces</rationale>
<variants_checked>file:function pairs you grepped for the same
pattern, and whether each needed the fix</variants_checked>
<bypass_considered>the input variation you tried in step 5 and why it
no longer reaches the bad state</bypass_considered>
<test_note>where the regression test landed, or why none was
added</test_note>
If you determine the finding is NOT fixable as described (wrong file, code
already patched, finding is a false positive), emit:
<patch_diff>NONE</patch_diff>
<rationale>why no patch is appropriate</rationale>You are conducting authorized security research as part of a defensive
assessment. Your task: write a candidate fix for ONE verified vulnerability
finding in a codebase you have read-only access to.
You may use Read, Glob, and Grep ONLY on paths inside {REPO_PATH}. You may
NOT build, run, install, edit files on disk, or reach the network. You will
emit the fix as a unified diff in your final response; you will NOT apply it.
────────────────────────────────────────────────────────────────────────
FINDING:
id: {id}
file: {file}
line: {line}
category: {category}
severity: {severity}
title: {title}
description:
{description}
recommendation:
{recommendation or "(none provided)"}
────────────────────────────────────────────────────────────────────────
PROCEDURE:
1. READ THE CODE. Open {file} at line {line} and the surrounding function.
Understand what the code does — do not trust the finding's description as
the only source.
2. ROOT CAUSE FIRST. Trace backward from the cited sink to where the bad
value or missing check originates. The fix usually belongs there, not at
the line the scanner flagged. Name the root-cause location (file:line).
3. VARIANT HUNT. Grep for sibling call sites with the same pattern. Your fix
should cover all of them, or your rationale should say why not.
4. MINIMAL DIFF. Smallest change that fixes the root cause. No refactoring,
no drive-by cleanup, no reformatting, no comment-only changes. Match the
surrounding code's style (brace placement, naming, error handling).
5. ADVERSARIAL SELF-CHECK. Re-read your diff as an attacker. Name one input
variation that would reach the same bad state without tripping your
change. If you can name one, your fix is at the wrong layer — go back to
step 2.
6. REGRESSION TEST. As part of the diff, add ONE test case that fails before
your change and passes after — placed wherever the project keeps its
tests (look for test_*/, *_test.*, tests/, spec/). If no test directory
exists, omit the test and say so in <test_note>.
────────────────────────────────────────────────────────────────────────
OUTPUT — your final response MUST contain exactly these tags. Emit the diff
verbatim between the markers; do NOT wrap it in ``` fences.
<patch_diff>
--- a/path/to/file
+++ b/path/to/file
@@ ... @@
context line
-removed line
+added line
</patch_diff>
<rationale>what changed and why, mechanically — file:line of root cause,
what the change enforces</rationale>
<variants_checked>file:function pairs you grepped for the same
pattern, and whether each needed the fix</variants_checked>
<bypass_considered>the input variation you tried in step 5 and why it
no longer reaches the bad state</bypass_considered>
<test_note>where the regression test landed, or why none was
added</test_note>
If you determine the finding is NOT fixable as described (wrong file, code
already patched, finding is a false positive), emit:
<patch_diff>NONE</patch_diff>
<rationale>why no patch is appropriate</rationale>Spawn
启动子代理
For each finding in , build a Task call with the prompt above
(substituting , , , , ,
, , , ).
.
findings[]{REPO_PATH}{id}{file}{line}{category}{severity}{title}{description}{recommendation}description: "patch {id}"If , shard into sequential batches of ~40 (each batch
one message). Per-finding shard checkpoint after each result is parsed.
len(findings) > ~40If any Task call returns instead of the
subagent's text, the runtime backgrounded it. Pick one recovery and use it
for the whole batch:
status: "async_launched"- If completion notifications arrive in your conversation: parse each
subagent's tagged blocks from its notification as it lands. Do not end your turn until every finding is accounted for.
result - If notifications do not arrive: do NOT poll transcript files. Re-spawn the missing patch subagents in a fresh Task batch (smaller shard, e.g. 10) and use the synchronous results. The same recovery applies to reviewer subagents in Phase 3.
对中的每个漏洞,使用上述提示词构建Task调用(替换、、、、、
、、、)。设置。
findings[]{REPO_PATH}{id}{file}{line}{category}{severity}{title}{description}{recommendation}description: "patch {id}"若,将其拆分为约40个漏洞一组的连续批次(每个批次对应一条消息)。解析每个结果后,为每个漏洞创建分片检查点。
len(findings) > ~40若任何Task调用返回而非子代理的文本,表示运行时已将其后台执行。选择以下一种恢复方式并对整个批次使用:
status: "async_launched"- 若对话中收到完成通知:在通知的中解析每个子代理的标签块。直到所有漏洞处理完成后再结束当前轮次。
result - 若未收到通知:不要轮询转录文件。在新的Task批次中重新启动缺失的补丁子代理(更小的分片,例如10个)并使用同步结果。 该恢复方式同样适用于第3阶段的审核子代理。
Parse
解析结果
From each Task result, extract the five tagged blocks. Tolerate leading/
trailing whitespace, stray ``` fences, and HTML-escaped entities (
— some runtimes escape angle brackets in notification
payloads; unescape before writing the diff). If is or
empty,
mark . Otherwise write the diff text to
(NN = zero-padded index in sorted order) and
record , , , .
<>&<patch_diff>NONEstatus: "no_patch"./PATCHES/bug_NN/patch.diffrationalevariants_checkedbypass_consideredtest_noteCheckpoint per finding: Write tool → =
, then Bash:
.
After all findings, write the consolidated phase payload to then:
./.patch-state/_chunk.tmp{"id": ..., "bug_nn": "NN", "status": ..., "rationale": ..., ...}python3 .claude/skills/_lib/checkpoint.py shard ./.patch-state <id> --from ./.patch-state/_chunk.tmp_chunk.tmppython3 .claude/skills/_lib/checkpoint.py save ./.patch-state 2 generate --from ./.patch-state/_chunk.tmp从每个Task结果中提取五个标签块。允许存在首尾空格、多余的```围栏和HTML转义实体(
— 部分运行时会在通知负载中转义尖括号;写入diff前需反转义)。若为或空,
标记。否则将diff文本写入(NN为排序后的零填充索引)并记录、、、。
<>&<patch_diff>NONEstatus: "no_patch"./PATCHES/bug_NN/patch.diffrationalevariants_checkedbypass_consideredtest_note每个漏洞的检查点:使用Write工具将以下内容写入 =
,然后执行Bash命令:
。所有漏洞处理完成后,将合并后的阶段负载写入,然后执行:
./.patch-state/_chunk.tmp{"id": ..., "bug_nn": "NN", "status": ..., "rationale": ..., ...}python3 .claude/skills/_lib/checkpoint.py shard ./.patch-state <id> --from ./.patch-state/_chunk.tmp_chunk.tmppython3 .claude/skills/_lib/checkpoint.py save ./.patch-state 2 generate --from ./.patch-state/_chunk.tmpPhase 3: Independent review (static mode only)
第3阶段:独立审核(仅静态模式)
One reviewer subagent per generated diff, all in ONE message,
.
subagent_type: "general-purpose"The reviewer never sees the finding's , , or
the patch author's . It gets only
plus the raw diff bytes, and re-derives whether the diff is a minimal,
in-scope fix by reading the source itself. This keeps any instructions
embedded in finding prose from reaching both the author and the gate.
descriptionrecommendationrationale{file, line, category}每个生成的diff对应一个审核子代理,所有子代理在同一条消息中启动,。
subagent_type: "general-purpose"审核员绝不会看到漏洞的、或补丁作者的。仅能获取
以及原始diff字节,并通过读取源代码自行判断diff是否为最小化、符合范围的修复方案。这样可避免漏洞描述中嵌入的指令同时影响补丁作者和审核环节。
descriptionrecommendationrationale{file, line, category}Reviewer prompt (assemble once, reuse per diff)
审核员提示词(组装一次,每个diff复用)
You are reviewing a candidate security patch as a maintainer would. You have
read-only access to the unpatched source at {REPO_PATH}. You may use Read,
Glob, Grep. You may NOT build, run, or apply the diff.
You have NOT seen the scanner's description of the vulnerability or the
patch author's reasoning. Work only from the location, the category, and the
diff.
LOCATION: {file}:{line}
CATEGORY: {category}
DIFF UNDER REVIEW:
<diff>
{diff_text — or, for diffs over ~50 lines, replace this block with:
"Read the diff at ./PATCHES/bug_NN/patch.diff" and let the reviewer Read it}
</diff>
────────────────────────────────────────────────────────────────────────
ANSWER FOUR QUESTIONS:
1. SCOPE. Does the diff touch only files/functions on the path between
{file}:{line} and its callers? List any hunk that falls outside that
path.
2. SUPPRESSION. Does the diff fix a root cause, or does it suppress the
symptom (try/except: pass, early-return on a magic value, deleting the
check that fired, lowering a log level)?
3. NEW SURFACE. Does the diff add parsing, trust a new input field, weaken
validation elsewhere, or remove a security-relevant check?
4. STYLE. 0-10: would you merge this as-is?
0-3 wrong layer / suppression; 4-6 correct but noisy; 7-10 minimal,
targeted, matches surrounding style.
────────────────────────────────────────────────────────────────────────
End your response with EXACTLY:
REVIEW: ACCEPT | REJECT
STYLE_SCORE: <0-10>
OUT_OF_SCOPE_HUNKS: <comma-separated file:line, or none>
REASON: <2-4 sentences citing specific diff hunks and source lines>
ACCEPT requires: in-scope, root-cause fix, no new attack surface,
style >= 5. Otherwise REJECT.You are reviewing a candidate security patch as a maintainer would. You have
read-only access to the unpatched source at {REPO_PATH}. You may use Read,
Glob, Grep. You may NOT build, run, or apply the diff.
You have NOT seen the scanner's description of the vulnerability or the
patch author's reasoning. Work only from the location, the category, and the
diff.
LOCATION: {file}:{line}
CATEGORY: {category}
DIFF UNDER REVIEW:
<diff>
{diff_text — or, for diffs over ~50 lines, replace this block with:
"Read the diff at ./PATCHES/bug_NN/patch.diff" and let the reviewer Read it}
</diff>
────────────────────────────────────────────────────────────────────────
ANSWER FOUR QUESTIONS:
1. SCOPE. Does the diff touch only files/functions on the path between
{file}:{line} and its callers? List any hunk that falls outside that
path.
2. SUPPRESSION. Does the diff fix a root cause, or does it suppress the
symptom (try/except: pass, early-return on a magic value, deleting the
check that fired, lowering a log level)?
3. NEW SURFACE. Does the diff add parsing, trust a new input field, weaken
validation elsewhere, or remove a security-relevant check?
4. STYLE. 0-10: would you merge this as-is?
0-3 wrong layer / suppression; 4-6 correct but noisy; 7-10 minimal,
targeted, matches surrounding style.
────────────────────────────────────────────────────────────────────────
End your response with EXACTLY:
REVIEW: ACCEPT | REJECT
STYLE_SCORE: <0-10>
OUT_OF_SCOPE_HUNKS: <comma-separated file:line, or none>
REASON: <2-4 sentences citing specific diff hunks and source lines>
ACCEPT requires: in-scope, root-cause fix, no new attack surface,
style >= 5. Otherwise REJECT.Spawn and parse
启动与解析
One Task per finding with . Parse the trailing block.
Attach , , , to the
finding. Set for every static-mode result
regardless of ACCEPT/REJECT — the label describes the verification class,
not the outcome.
status != "no_patch"reviewstyle_scoreout_of_scope_hunksreview_reasonverified: "static_review_only"Checkpoint: Write tool → :
Then Bash:
./.patch-state/_chunk.tmp{"phase": 3, "findings": [...]}python3 .claude/skills/_lib/checkpoint.py save ./.patch-state 3 review --from ./.patch-state/_chunk.tmp对每个的漏洞启动一个Task。解析末尾的结果块。将、、、附加到漏洞记录中。无论审核结果是ACCEPT还是REJECT,为所有静态模式结果设置——该标签描述的是验证类别,而非结果。
status != "no_patch"reviewstyle_scoreout_of_scope_hunksreview_reasonverified: "static_review_only"检查点:使用Write工具将以下内容写入:
然后执行Bash命令:
./.patch-state/_chunk.tmp{"phase": 3, "findings": [...]}python3 .claude/skills/_lib/checkpoint.py save ./.patch-state 3 review --from ./.patch-state/_chunk.tmpPhase 4: Output
第4阶段:输出
4a. Per-finding patch_result.json
patch_result.json4a. 每个漏洞的patch_result.json
patch_result.jsonFor each finding (both modes), Write
:
./PATCHES/bug_NN/patch_result.jsonjson
{
"id": "f003",
"source": "TRIAGE.json#2",
"title": "...",
"file": "...",
"line": 0,
"category": "...",
"severity": "HIGH",
"owner_hint": "...",
"mode": "exec" | "static",
"verified": "ladder_passed" | "ladder_failed" | "static_review_only",
"review": "ACCEPT" | "REJECT" | null,
"style_score": 0,
"out_of_scope_hunks": [],
"rationale": "...",
"variants_checked": "...",
"bypass_considered": "...",
"test_note": "...",
"review_reason": "...",
"verdict": { "t0_builds": true, "...": "(exec mode only, from pipeline)" }
}In exec mode, also Read the pipeline's
and Write its bytes to
so both modes land in the same place.
<findings_path>/reports/bug_NN/patch.diff./PATCHES/bug_NN/patch.diff对每个漏洞(两种模式),写入
:
./PATCHES/bug_NN/patch_result.jsonjson
{
"id": "f003",
"source": "TRIAGE.json#2",
"title": "...",
"file": "...",
"line": 0,
"category": "...",
"severity": "HIGH",
"owner_hint": "...",
"mode": "exec" | "static",
"verified": "ladder_passed" | "ladder_failed" | "static_review_only",
"review": "ACCEPT" | "REJECT" | null,
"style_score": 0,
"out_of_scope_hunks": [],
"rationale": "...",
"variants_checked": "...",
"bypass_considered": "...",
"test_note": "...",
"review_reason": "...",
"verdict": { "t0_builds": true, "...": "(exec mode only, from pipeline)" }
}在执行模式下,还需读取流水线的
并将其内容写入
,确保两种模式的输出位置一致。
<findings_path>/reports/bug_NN/patch.diff./PATCHES/bug_NN/patch.diff4b. ./PATCHES.json
./PATCHES.json4b. ./PATCHES.json
./PATCHES.jsonjson
{
"patch_completed": true,
"mode": "exec" | "static",
"repo": "...",
"summary": {
"input_count": 0,
"patched": 0,
"no_patch": 0,
"accepted": 0,
"rejected": 0,
"ladder_passed": 0
},
"findings": [ { ...patch_result.json shape... } ]
}json
{
"patch_completed": true,
"mode": "exec" | "static",
"repo": "...",
"summary": {
"input_count": 0,
"patched": 0,
"no_patch": 0,
"accepted": 0,
"rejected": 0,
"ladder_passed": 0
},
"findings": [ { ...patch_result.json shape... } ]
}4c. ./PATCHES.md
(incremental)
./PATCHES.md4c. ./PATCHES.md
(增量生成)
./PATCHES.mdStep 1 — header. Write tool → (clobbers prior):
./PATCHES.mdmarkdown
undefined步骤1 — 头部:使用Write工具写入(覆盖原有内容):
./PATCHES.mdmarkdown
undefinedCandidate Patches
候选补丁
{if mode == "static":}
Static review only. These diffs were authored and reviewed by independent agents reading source. They were NOT compiled, run, or re-attacked. Read each diff yourself before applying — seefor what to look for.docs/patching.md#reviewing-generated-patches
{if mode == "exec":}
Execution-verified. Each diff passed (or failed) the pipeline verification ladder: build → reproduce → regress → re-attack. The ladder proves the crash is gone, not that the diff introduces no new problems.
Input: {findings_path} · Repo: {repo} · {N} findings → {M} diffs
**Step 2 — per finding** (sorted: ACCEPT/ladder_passed first, then by
severity). Write `./.patch-state/_chunk.tmp`:
````markdown{if mode == "static":}
仅静态审核。这些diff由独立代理读取源代码生成并审核。未经过编译、运行或重攻击测试。应用前请自行审核每个diff——详见了解审核要点。docs/patching.md#reviewing-generated-patches
{if mode == "exec":}
执行验证通过。每个diff已通过(或未通过)流水线验证流程:构建→复现→回归→重攻击。该流程仅证明崩溃已修复,不保证diff未引入新问题。
输入来源:{findings_path} · 代码库:{repo} · {N}个漏洞 → {M}个diff
**步骤2 — 每个漏洞详情**(排序规则:ACCEPT/ladder_passed优先,然后按严重性排序)。写入`./.patch-state/_chunk.tmp`:
````markdownbug_{NN}: [{severity}] {title} ({id})
bug_{NN}: [{severity}] {title} ({id})
{file}:{line}PATCHES/bug_{NN}/patch.diffRationale: {rationale}
Variants checked: {variants_checked}
Bypass considered: {bypass_considered}
{if review == "REJECT":}
Rejected by reviewer: {review_reason} {if out_of_scope_hunks:} Out-of-scope hunks: {out_of_scope_hunks}
Then `checkpoint.py append ./PATCHES.md --from ./.patch-state/_chunk.tmp`.
**Step 3 — footer.** Append a `## Skipped` table for findings with no `file`
or `status == "no_patch"`, one line each with the reason.
**Checkpoint (final):** Bash:
`python3 .claude/skills/_lib/checkpoint.py done ./.patch-state 4`{file}:{line}PATCHES/bug_{NN}/patch.diff修复说明:{rationale}
已检查变体:{variants_checked}
已考虑绕过方式:{bypass_considered}
{if review == "REJECT":}
审核拒绝原因:{review_reason} {if out_of_scope_hunks:} 超出范围的代码块:{out_of_scope_hunks}
然后执行`checkpoint.py append ./PATCHES.md --from ./.patch-state/_chunk.tmp`。
**步骤3 — 尾部**:添加`## 已跳过漏洞`表格,列出无`file`字段或`status == "no_patch"`的漏洞,每行包含一个漏洞及原因。
**最终检查点**:执行Bash命令:
`python3 .claude/skills/_lib/checkpoint.py done ./.patch-state 4`4d. Terminal summary
4d. 终端摘要
Under ~10 lines:
Patches generated ({mode} mode): {N} findings → {M} diffs.
Accepted: {n} {title of top accepted}
Rejected: {n}
No patch: {n}
{if exec:} Ladder passed: {n}/{M}
Wrote ./PATCHES/bug_NN/, ./PATCHES.md, ./PATCHES.json
{if static:} These are drafts. Review before applying — see docs/patching.md.控制在约10行以内:
补丁生成完成({mode}模式):{N}个漏洞 → {M}个diff。
已接受: {n} {top accepted的标题}
已拒绝: {n}
无补丁: {n}
{if exec:} 流水线验证通过:{n}/{M}
已写入 ./PATCHES/bug_NN/、./PATCHES.md、./PATCHES.json
{if static:} 这些为草稿版本。应用前请审核——详见docs/patching.md。Guard rails
防护规则
- The skill never applies diffs. No , no
git apply, no Edit againstpatch. If you find yourself needing to, the design is wrong.--repo - Write only under and
./PATCHES/../.patch-state/ - Reviewer isolation. The reviewer prompt receives and nothing else from the finding. Do not pass it
{file, line, category, diff},description,recommendation, or the patch author'sexploit_scenario.rationale - Always set . Forking would leak every finding's prose into every patch subagent.
subagent_type - All Task calls for a phase in ONE message. Serial spawning is correct but N× slower.
- Checkpoint before starting the next phase, every time.
- Exec mode delegates, never reimplements. If isn't on PATH, stop and tell the user; don't fall back to static mode silently.
vuln-pipeline patch
- 技能绝不会应用diff。禁止执行、
git apply或对patch执行Edit操作。若发现需要这些操作,说明设计存在错误。--repo - 仅能写入和
./PATCHES/目录。./.patch-state/ - 审核员隔离。审核员提示词仅接收,不接收漏洞的其他信息。不要传递
{file, line, category, diff}、description、recommendation或补丁作者的exploit_scenario。rationale - 必须设置。若不设置,会将每个漏洞的描述泄露给所有补丁子代理。
subagent_type - 同一阶段的所有Task调用放在同一条消息中。串行启动虽然正确,但速度慢N倍。
- 进入下一阶段前必须创建检查点,每次都要执行。
- 执行模式仅委托,绝不重新实现。若不在PATH中,终止并告知用户;不要静默回退到静态模式。
vuln-pipeline patch
Testing this skill
技能测试
Static mode against the canary fixture:
/vuln-scan targets/canary
/triage VULN-FINDINGS.json --repo targets/canary --auto
/patch TRIAGE.json --repo targets/canary --top 3Expected: three diffs under , each
, , style ≥ 7 for the
planted overflow/UAF/format-string bugs.
PATCHES/bug_00..02/verified: "static_review_only"review: ACCEPTExecution-verified mode against pipeline output:
vuln-pipeline run drlibs --runs 3 --parallel --stream --model <m>
/patch results/drlibs/<ts>/ --model <m>Expected: delegates to , surfaces
per bug, copies diffs into .
vuln-pipeline patchverified: "ladder_passed"./PATCHES/针对canary测试用例的静态模式:
/vuln-scan targets/canary
/triage VULN-FINDINGS.json --repo targets/canary --auto
/patch TRIAGE.json --repo targets/canary --top 3预期结果:目录下生成三个diff,每个diff的、、风格评分≥7,对应植入的溢出/UAF/格式化字符串漏洞。
PATCHES/bug_00..02/verified: "static_review_only"review: ACCEPT针对流水线输出的执行验证模式:
vuln-pipeline run drlibs --runs 3 --parallel --stream --model <m>
/patch results/drlibs/<ts>/ --model <m>预期结果:委托给,每个漏洞标记,将diff复制到目录。
vuln-pipeline patchverified: "ladder_passed"./PATCHES/Design notes
设计说明
- TRIAGE.json is canonical input because patching unverified findings wastes tokens on false positives. VULN-FINDINGS.json is accepted with a warning for convenience.
- Static mode emits a regression test inside the diff rather than running it. The skill cannot execute target code (constraint of the static pipeline); the test is for the human who applies the diff.
- Reviewer never sees finding prose. Target source can contain
injected instructions that survive into a scanner's field. The patch author sees that prose (it has to, to know what to fix); the reviewer doesn't, so injected text cannot pass its own gate.
description - is the verification class, not pass/fail.
verifiedmeans "an agent read it" regardless of ACCEPT/REJECT.static_review_only/ladder_passedmeans "ASAN decided." Downstream tooling should branch on this field, not onladder_failed.review - Output shape matches the pipeline () so consumers don't care which mode produced it.
PATCHES/bug_NN/{patch.diff, patch_result.json}
- TRIAGE.json是标准输入,因为为未验证漏洞生成补丁会浪费令牌在假阳性上。为方便使用,VULN-FINDINGS.json会被接受但会给出警告。
- 静态模式在diff中包含回归测试,而非运行测试。技能无法执行目标代码(静态流水线的约束);测试供应用diff的人员使用。
- 审核员绝不会看到漏洞描述。目标源代码可能包含注入的指令,这些指令会保留到扫描器的字段中。补丁作者需要看到这些描述(才能知道要修复什么);审核员看不到,因此注入的文本无法通过审核环节。
description - 表示验证类别,而非通过/失败。
verified表示“已由代理读取”,无论审核结果是ACCEPT还是REJECT。static_review_only/ladder_passed表示“由ASAN判定”。 下游工具应根据该字段分支处理,而非ladder_failed字段。review - 输出格式与流水线一致(),因此消费者无需关心生成模式。
PATCHES/bug_NN/{patch.diff, patch_result.json}