关于 snyk-remediation
以 Snyk 扫描结果为依据的安全漏洞处理流程,涵盖问题分级、修复计划、实施和复测。它通过用户确认来界定范围并批准计划,避免未经同意直接修复。
主要功能
- 01收集 SAST 与 SCA 扫描结果
- 02按用户指定范围筛选问题
- 03制定逐项修复计划并等待批准
- 04复测并记录解决情况
- 05通过确认流程准备 PR
适用场景
- 01整理项目中的 Snyk 漏洞发现
- 02优先处理指定严重级别的问题
- 03跟踪漏洞修复及复测结果
MCP 相关
流程调用 Snyk MCP 工具 `snyk_trust`、`snyk_code_scan` 和 `snyk_sca_scan` 来信任项目路径并运行扫描。
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ incu-tech/ incuway --skill snyk-remediation安装后在 Claude Code 中输入/snyk-remediation确认已加载。
附带文件agents/openai.yaml
详细介绍
Snyk 修复流程
一个由关卡驱动的工作流,用于查找并修复 Snyk 检测到的安全漏洞,避免对范围或可接受风险妄下判断。先收集信息并了解扫描背景,然后依次进行扫描、分类、规划、修复、验证,并在关键决策点获得用户明确确认后创建 PR。未经批准的计划不得应用任何修复。
仓库资格检查(先于所有其他操作)
在 Phase 0 之前,检查 ~/.ways/config.yaml 中的 blacklist(格式:incu-base 的 global-config 规则,始终启用)
是否匹配当前仓库。如果匹配,告知用户该仓库已被 incu-way 列入黑名单,并询问是仍要继续(仅限本次例外)还是停止——在用户回复之前,不得运行任何阶段。
文件不存在或没有匹配项:正常继续。
Phase 0 — 信息收集与扫描
目标: 收集 SAST 和 SCA 扫描检测到的所有当前漏洞。
步骤
- 扫描前确认信息收集背景:
- 要扫描的项目绝对路径
- 用户希望仅审查、分类还是修复
- 已知的紧急程度、环境或业务限制
- 用户希望考虑的任何先前扫描背景
- 如果项目文件夹尚未获信任,先使用项目绝对路径调用
snyk_trust。 - 使用
snyk_code_scanMCP 工具运行 SAST 扫描:path: <absolute project path> severity_threshold: low - 使用
snyk_sca_scanMCP 工具运行 SCA 扫描:path: <absolute project path> severity_threshold: low all_projects: true - 收集两份结果中的所有问题。
如果 snyk_trust、snyk_code_scan 或 snyk_sca_scan 不可用,或在返回发现结果前失败,请在 Gate 1 之前停止,报告确切缺失的工具或故障,并请用户安装/配置 Snyk 或提供扫描输出。不得编造发现结果,也不得根据过时数据继续制定修复计划。
Phase 0 防护措施
- 不要假设用户希望修复所有发现的问题。扫描提供证据;范围由用户确定。
- 不要仅凭技术严重程度推断业务优先级。
- 如果路径、扫描目标或期望的修复范围不明确,请先澄清再继续。
Phase 0 退出条件
进入 Phase 1 之前,Claude 应能够说明:
- 使用的项目路径和扫描目标
- 用户希望仅审查、分类还是修复
- 已知的业务或环境限制
- 发现列表反映的是实际扫描证据,而非假设
Phase 1 — 发现结果报告
目标: 以清晰、可执行的格式向用户展示所有发现结果。
报告格式
创建一个 Markdown 表格,每个发现结果占一行:
# Snyk Security Findings — {YYYY-MM-DD}
## Summary
- SAST issues: {N} (Critical: X, High: X, Medium: X, Low: X)
- SCA issues: {N} (Critical: X, High: X, Medium: X, Low: X)
- Total: {N}
## Findings
| # | Type | Severity | Title | File / Package | CWE / CVE | Impact | Fix available |
|---|------|----------|-------|----------------|-----------|--------|---------------|
| 1 | SAST | High | SQL Injection | `lib/db/queries/contacts.ts:42` | CWE-89 | Attacker can exfiltrate DB data via crafted input | Yes — sanitize input |
| 2 | SCA | Critical | Prototype Pollution | `[email protected]` | CVE-2019-10744 | Remote code execution via crafted payload | Yes — upgrade to `[email protected]` |
列定义:
- 类型:
SAST(源代码)或SCA(依赖项) - 严重程度: Critical / High / Medium / Low
- 标题: Snyk 问题标题
- 文件 / 软件包: 对于 SAST:
filePath:line。对于 SCA:package@version - CWE / CVE: SAST 使用 CWE,SCA 使用 CVE(如果有)
- 影响: 用一句话说明攻击者在利用该漏洞后可能造成的后果
- 有可用修复: 是(附简要说明)或否
Gate 1 — 范围确认
展示表格后:
- 询问用户:“这些是发现的问题。你希望修复哪些严重程度级别?(例如,Critical + High,或全部。)我会根据你的回答确定修复计划的范围。”
- 停止。在用户确定范围之前,不得继续。
不得将扫描输出本身视为修复授权。Gate 1 用于确定哪些发现确实属于修复范围。
隔离设置(紧接 Gate 1 之后)
写入任何文件之前,询问用户希望如何隔离工作:
你希望我在当前检出中创建一个新分支进行操作,还是创建一个单独的 git worktree?
严格按照用户的回答操作: 询问后停止;在用户做出选择前,不得创建分支或 worktree。
如果当前检出存在未提交更改,在切换分支或创建 worktree 之前停止并询问。
选项 A — 在当前检出中创建分支
# Run from the repo root
git switch develop
git pull --ff-only
git switch -c fix/security-{slug}
后续所有工作——文档、代码、提交——都在当前检出中的此分支上进行。切勿直接向 develop 或 main 写入文件。
选项 B — 使用单独的工作树
仅在 .worktrees/ 下创建工作树。不要向用户询问路径。
# Run from the repo root
git fetch origin develop
mkdir -p .worktrees
git worktree add .worktrees/security-{slug} -b fix/security-{slug} origin/develop
后续所有工作——文档、代码、提交——都仅在此工作树内进行。切勿直接向 develop 或 main 写入文件。
状态跟踪 — .ways/state.json
遵循 ways/v1alpha1 状态契约——规范的 .ways/state.json 格式(schemaVersion 为 2),该格式随 始终启用的 state-contract 规则一同提供;ways add 会将该规则添加到项目中,因此你已了解相关内容(无需查找路径)。对于维护人员,此仓库中的源文件位于 ways/rulepacks/state-contract/。不要在此技能中复制或臆造架构。
特定于此工作流的值:
flow:securityway:incu/security·discipline:security(可选的wayVersion来自 way 清单)- 分支模式:
fix/security-{slug} - 初始
phase:findings isolationType:根据隔离方式选择branch或worktree- 文档:
docs/security/{slug}/FINDINGS.md、docs/security/{slug}/PLAN.md、docs/security/{slug}/RESOLUTION.md - Gate:
plan、resolution、pr-develop、pr-main
会话开始时,如果 .ways/state.json 存在,则读取它。如果其 branch 与当前 fix/security-{slug} 分支匹配,报告当前阶段、下一步和待处理的 Gate,并从该状态继续。如果文件不存在,或文件存在但其 branch 不匹配(从已合并事项继承的过期文件),则从阶段 0 开始,并在 Gate 1 后完成所选隔离设置后,立即在 .ways/state.json 创建或覆盖该文件。每次转换阶段时,也要更新 lastPhase(即将离开的阶段)。
更新节点(阶段 → 写入内容):
| 时机 | phase | 文档 / Gate / 步骤 |
|---|---|---|
| 写入 FINDINGS.md | findings | FINDINGS.md → approved |
| 起草 PLAN.md | plan | PLAN.md → in-review |
| Gate 2 通过(计划) | implementation | PLAN.md → approved;Gate plan → passed;生成 steps——每个纳入范围的发现对应一项,且状态均为 todo |
| 修复每项发现 | implementation | 将对应步骤标记为 in-progress → done(或 blocked)——每项发现都要立即写入状态文件,不能批量拖到最后 |
| 写入 RESOLUTION.md | validation | RESOLUTION.md → approved |
| Gate 3 通过(解决方案) | validation | Gate resolution → passed |
| 打开 fix→develop PR | pr-develop | Gate pr-develop → 仍为 pending;将其 url 设为 PR 链接 |
| PR 合并到 develop | pr-develop | Gate pr-develop → passed |
| 打开 develop→main PR | pr-main | Gate pr-main → 仍为 pending;将其 url 设为 PR 链接 |
| PR 合并到 main | done | Gate pr-main → passed |
在 Gate 2 生成的 steps(每个纳入范围的发现对应一项)会显示在看板上,作为修复进度。
不要自行提交 .ways/state.json——只需写入它。当用户希望保存检查点时,建议调用 incu-way-prepare-pr,它会将该检查点与此阶段的文档和代码一并提交。
阶段 2 — 记录发现
目标: 将发现报告存档,作为审计轨迹的入口。
保存位置
保存到所选工作位置:
docs/security/{YYYY-MM-DD}-{short-slug}/FINDINGS.md
Slug: 用 2–4 个词概括主要问题类型的 kebab 格式摘要,例如:
2026-05-15-xss-sqli-drizzle2026-03-10-prototype-pollution-deps
FINDINGS.md 结构
# Security Findings — {YYYY-MM-DD}
## Scan metadata
- Date: {YYYY-MM-DD}
- Tool: Snyk (SAST + SCA)
- Branch scanned: {branch name}
- Scope agreed: {e.g., Critical + High}
## Findings table
{paste the full table from Phase 1}
## Out of scope
{List findings the user chose NOT to fix, with a brief reason}
保存后:
- 说明:"发现已记录在
docs/security/{slug}/FINDINGS.md。现在我将针对已确认的范围起草修复计划。" - 直接进入阶段 3(无需 Gate——用户已在 Gate 1 确认范围)。
阶段 3 — 修复计划
目标: 为每项纳入范围的发现设计具体且便于审查的修复方案。
保存位置
docs/security/{slug}/PLAN.md
PLAN.md 结构
# Remediation Plan — {YYYY-MM-DD}
## Branch
`fix/security-{slug}`
## Isolation mode
current checkout branch | separate worktree
## Findings to fix
### Finding #1 — {Title} ({Severity})
- **Type:** SAST / SCA
- **Location:** {file:line or package@version}
- **Root cause:** {one sentence}
- **Fix approach:** {concrete action: upgrade X to Y / sanitize input at line Z / replace API call / etc.}
- **Risk of fix:** Low / Medium / High — {why}
- **Verification:** {how to confirm it's fixed: re-scan + specific test}
### Finding #2 — ...
Gate 2 — 计划审批
编写计划后:
- 说:“修复计划已准备就绪,位于
docs/security/{slug}/PLAN.md。请在我开始编码前,审阅每项发现的修复方案。” - 停止。在用户表示 OK 前不要继续。
第 4 阶段 — 实施
目标: 在用户选择的隔离分支或工作树中应用修复。
设置
继续使用第 2 阶段前选择的隔离模式。除非用户要求更改模式,否则不要创建第二个分支或工作树。
规则
- 一次修复一项发现。每修复一项后,建议调用
incu-way-prepare-pr来提交;不要自行提交:fix(security): {finding title} — {CWE or CVE} Resolves finding #{N} from docs/security/{slug}/FINDINGS.md Fix: {one-line description of what changed} - 对于 SCA 升级: 更新
package.json,运行pnpm install,并确认没有破坏对等依赖。 - 对于 SAST 修复: 应用代码更改,并添加或更新一个用于测试易受攻击路径的测试。
- 每次修复后、建议提交前,运行
pnpm typecheck && pnpm lint && pnpm test。
进度跟踪
随着进度更新 PLAN.md——修复每项发现后,将其标记为对应的提交 SHA:
- **Status:** Fixed in `abc1234`
第 5 阶段 — 验证
目标: 确认所有修复均有效,且未引入回归问题。
步骤
- 重新运行 SAST 扫描:
snyk_code_scan — path: <absolute path to the selected working location>, severity_threshold: low - 重新运行 SCA 扫描:
snyk_sca_scan — path: <absolute path to the selected working location>, severity_threshold: low, all_projects: true - 运行完整测试套件:
pnpm typecheck && pnpm lint && pnpm test && pnpm build
解决情况文档
保存 docs/security/{slug}/RESOLUTION.md:
# Resolution Report — {YYYY-MM-DD}
## Re-scan results
- SAST re-scan: {N issues remaining} (was {N before})
- SCA re-scan: {N issues remaining} (was {N before})
- Fixed: {list of finding titles resolved}
- Remaining (out of scope): {list}
## Test suite
- `pnpm typecheck`: ✅ / ❌
- `pnpm lint`: ✅ / ❌
- `pnpm test`: ✅ / ❌
- `pnpm build`: ✅ / ❌
## Evidence
{Paste key output from re-scans — zero-issue confirmation or remaining out-of-scope items}
Gate 3 — 验证签核
编写解决情况文档后:
- 说:“修复已应用并通过验证。解决情况报告位于
docs/security/{slug}/RESOLUTION.md。所有范围内的发现均已解决,测试全部通过。请在我创建 PR 前进行审阅。” - 停止。等待用户确认。
第 6 阶段 — Pull Request
目标: 通过经过审阅的 PR 合入安全修复。
分支流程
fix/security-{slug} → develop → main
(PR 1) (PR 2)
PR 1 — fix/security-{slug} → develop
Gate 3 通过后,建议调用 incu-way-prepare-pr,推送 fix/security-{slug} 并向 develop 创建 PR。不要自行推送或运行 gh pr create。
供 incu-way-prepare-pr 使用的建议 PR 标题/正文:
Title: fix(security): {short summary of what was fixed}
PR 正文必须包含:
- 摘要: 修复了哪些漏洞(类型、严重程度、数量)。
- 发现: 链接到
docs/security/{slug}/FINDINGS.md。 - 计划: 链接到
docs/security/{slug}/PLAN.md。 - 解决情况: 链接到
docs/security/{slug}/RESOLUTION.md。 - 检查清单: snyk-code ✅、snyk-deps ✅、typecheck ✅、lint ✅、tests ✅、build ✅。
创建 PR 后,分享 PR URL。停止。未经用户批准,不要合并。
PR 2 — develop → main
PR 1 合并后,再次建议调用 incu-way-prepare-pr,创建从 develop → main 的 PR:
Title: release(security): {slug}
Body: Promotes security remediations from fix/security-{slug}. See docs/security/{slug}/ for full audit trail.
创建后,分享 URL 并等待用户批准。
快速参考 — 各 Gate
| Gate | 触发条件 | 要说的话 | 阻塞条件 |
|---|---|---|---|
| 1 | 展示发现表格 | “你想修复哪些严重程度级别?” | 用户确定范围 |
| 2 | 编写 PLAN.md | “计划已准备就绪,位于 docs/security/{slug}/PLAN.md。请审阅。” | 用户表示 OK |
| 3 | 编写 RESOLUTION.md | “修复已通过验证。请在创建 PR 前审阅解决情况报告。” | 用户表示 OK |
| 4 | 用户确认 | 建议调用 incu-way-prepare-pr 创建 fix→develop 的 PR;用户运行后分享 URL | 用户批准 PR |
| 5 | PR 1 合并 | 建议调用 incu-way-prepare-pr 创建 develop→main 的 PR;用户运行后分享 URL | 用户批准 PR |
每次扫描的文档布局
docs/security/{YYYY-MM-DD}-{slug}/
FINDINGS.md — raw scan results + agreed scope (Phase 2)
PLAN.md — fix approach per finding (Phase 3)
RESOLUTION.md — re-scan evidence + test results (Phase 5)
不要做的事
- 在 Gate 2(计划审批)通过前,不要应用任何修复。
- 未先征求用户意见,不要修复范围外的发现。
- 未得到用户明确指示,不要擅自推断修复范围、可接受风险或业务优先级。
- 如果预期范围或修复取舍仍不明确,不要直接将扫描结果转化为修复计划。
- 不要跳过 Phase 5 中的重新扫描——仅通过测试并不能确认漏洞已修复。
- 如果
RESOLUTION.md未显示重新扫描结果干净,不要创建 PR。 - 不要直接合并——始终通过 PR 进行,即使只是微不足道的依赖升级。
- 未得到用户明确指示,不要使用
.snyk忽略规则屏蔽 Snyk 发现。 - 在选择隔离模式前,不要将 FINDINGS.md、PLAN.md 或任何其他文件写入
develop/main——Gate 1 通过后会立即设置分支或工作树,从一开始就应将所有文件放入所选工作位置。