結構化輸出

結構化輸出

第 5 階段把每筆存活的發現轉成可被機器讀取的 JSON,符合 report-schema.json,並由零依賴的 Node 驗證器檢查。

schema 是一個 oneOf:一筆發現要嘛是 confirmed(完整 trace、執行與修補),要嘛是 rejected(調查後發現事實有誤)。各處都強制 additionalProperties:false。

Confirmed 發現——必填欄位

verdictconst "confirmed"

標記為已驗證的漏洞。

titlestring

簡潔、標準的漏洞標題。

descriptionstring

完整說明,含 PoC 與觀察到的輸出。

root_causestring

一句話:「[函式] 在 [檔案] 沒有做 [動作],導致 [後果]」。

intended_behaviorstring

開發者原本想做的、非漏洞的邏輯。

tracearray (≥2)

從 entrypoint → … → sink 的循序步驟;每步 {kind,file,line,scope,description}。第一步須為 entrypoint、最後一步須為 sink。

conditionsarray

事實前提(認證等級、角色、設定、時序……)。預設即可利用則為空陣列。

executionobject

{attacker_perspective, payloads[], instructions[], expected_result}。

remediationobject

{strategy, code_changes[]}——修補。

severityobject

{likelihood{score,reason}, impact{score,reason}, overall_severity}。

confidenceobject

{score, reason}——記下缺失檔案或模糊的資料流。

Rejected 發現

verdictconst "rejected"

所述行為事實錯誤,或該程式碼路徑不存在。

reasonstring

哪些具體主張錯了,附程式碼證據。

一筆 confirmed 發現(節錄)

{
  "verdict": "confirmed",
  "title": "Stored XSS in comment rendering",
  "root_cause": "renderComment in views/comment.js does not escape body, allowing script injection",
  "trace": [
    { "kind": "entrypoint", "file": "routes/comment.js", "line": 42,
      "scope": "createComment", "description": "req.body.text stored unsanitized" },
    { "kind": "sink", "file": "views/comment.js", "line": 17,
      "scope": "renderComment", "description": "body interpolated into innerHTML" }
  ],
  "severity": {
    "likelihood": { "score": "high", "reason": "any authenticated user can post" },
    "impact":     { "score": "high", "reason": "fires for every viewer" },
    "overall_severity": "high"
  },
  "confidence": { "score": "high", "reason": "trace verified against source" }
}

validate-findings.cjs

一個零依賴的 Node 驗證器。它直接讀 report-schema.json,檢查必填欄位、enum 值、結構限制、additionalProperties,以及 trace 是否 entrypoint → sink。它只做結構檢查——確認 JSON 符合 schema,而非確認發現正確。事實查核是第 6 階段的工作。

$node validate-findings.cjs findings.json