Skip to content

feat: add vulnerability retest branches with an isolated evidence log - #348

Merged
Ed1s0nZ merged 1 commit into
AIPentest:mainfrom
Sycun:feat/vulnerability-retest
Oct 10, 2026
Merged

Ed1s0nZ merged 1 commit into
AIPentest:mainfrom
Sycun:feat/vulnerability-retest

Conversation

@Sycun

@Sycun Sycun commented Oct 9, 2026

Copy link
Copy Markdown
Contributor

做了什么

漏洞列表每条新增「复测」入口:从原始对话创建独立分支(快照历史与模型轨迹),在分支里多轮验证,不写回原对话。

  • POST /api/vulnerabilities/:id/retest 建分支并持久化提示词,响应丢失 / 切页 / 刷新都能回到该分支继续发送
  • 新增 MCP 工具 update_vulnerability_status;复测分支只能读写它自己那一条漏洞
  • {{vulnerability_id}} / {{conversation_id}} / {{source_conversation_id}} 发送时替换,首轮与后续轮都生效
  • 复测提示词默认带上运维者写的 retest_notes(那正是「怎么验证已修复」)

两处值得单说的实现决定:

  • 证据写入只读列 vulnerabilities.retest_log,不追加进 retest_notes。后者是运维者手写字段、编辑弹窗整体覆盖保存,混用会让一次普通编辑静默删掉复测痕迹。
  • 复制消息时把时间戳重新绑成 time.Time。DATETIME 扫进 string 会被 database/sql 转成 RFC3339Nano,而 AddMessage 写的是驱动的空格格式,GetMessages 又按 created_at 裸字符串排序 —— 混格式会让分支的新一轮问答排到继承历史上面。

数据库

新增表 vulnerability_retests + 列 vulnerabilities.retest_log。列在 migrateVulnerabilitiesTable 里 ALTER,同时补进 migrateVulnerabilitiesConversationFK 的重建列清单(否则老库走重建路径会丢列)。均为启动时幂等迁移,无需手工操作。

验证

go build ./... / go vet / go test ./... 全过;node --test web/static/js/*.test.cjs 287/287。

新增回归测试都先证红再转绿:

  • TestVulnerabilityRetestLogSurvivesOperatorEdit —— 把 UPDATE 的列名改回 retest_notes 即红
  • TestVulnerabilityRetestBranchKeepsChronologicalOrder —— 把时间戳改回 string 透传即红(position 0 = "retest turn", want "original request")
  • 前端 the retest prompt carries the operator-written verification method —— 把预填改回纯默认提示词即红

实机跑通完整链路:建分支 → 自动发送 → agent 复测 → update_vulnerability_status 落库 → retest_log 留痕且 retest_notes 不变。

顺带

chat-scroll-refresh.test.cjs / hitl-approval-ui.test.cjs 里把 ?v= 版本号写死的断言改成版本无关(与同文件既有的 style.css?v=[A-Za-z0-9._-]+ 写法一致),否则每次改缓存标记都会打红。monitor.js / chat-scroll.js 两处仍是写死的,本 PR 未动。

Retesting a finding creates an independent conversation branch that
snapshots the source history and model trace, so verification can run
multi-turn without writing to the original session.

- POST /api/vulnerabilities/:id/retest creates the branch and persists the
  prompt, so a lost response, navigation or refresh can resume it
- new update_vulnerability_status tool closes the loop; a retest branch may
  only read and update its own finding
- {{vulnerability_id}}, {{conversation_id}} and {{source_conversation_id}}
  resolve on send, in the first turn and in follow-ups
- evidence appends to a read-only vulnerabilities.retest_log column instead
  of retest_notes: that field is operator-authored and the edit form
  rewrites it wholesale, so a routine edit used to erase the retest trail
- the retest prompt is prefilled with the operator's retest_notes, which
  already states how to verify the fix
- copied messages are re-bound as time.Time. Scanning a DATETIME column into
  a string yields RFC3339Nano while AddMessage writes the driver's
  space-separated format, and messages sort on the raw created_at text, so a
  branch rendered its new turn above the inherited history
@Ed1s0nZ
Ed1s0nZ merged commit e77606b into AIPentest:main Oct 10, 2026
6 checks passed
@Sycun
Sycun deleted the feat/vulnerability-retest branch October 16, 2026 15:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants