這個系列從「如何不被一個看似合理的 XSS 結論騙過去」開始,一路將請求、回應、DOM 觀察、自動驗證與作者核對拆開。到 Day 25,這些資料已經能用單一 CLI 盤點、建置與驗證。今天要回答的不再是「下一個功能是什麼」,而是「這個作品什麼時候才算完成」。
我的答案是:**XSS 證據工作台的功能今天完成了。**我把本次建置視為 1.0.0 的 release candidate,從現在起不再加入新情境或新探針。不過,「功能完成」不等於「整體驗收已通過」;版本欄位雖然已是 1.0.0,今天仍是候選階段,要等 Day 27 的回歸、可重現與篡改測試都過關,才正式凍結 v1.0。
我執行建置後,evidence-bundle.json 的驗收摘要得到:
| 項目 | 數量 |
|---|---|
| XSS 實驗情境 | 5 |
| 保存案例 | 15 |
| 觀察到固定探針執行 | 5 |
| 未觀察到固定探針執行 | 10 |
| 保存表單 | 6 |
| AI 報告現行規則重驗通過 | 15 |
| 作者核對紀錄 | 5 |
5 種情境是 HTML 屬性、行內 JavaScript 字串、URL fragment 與 DOM、POST 反射,以及儲存後讀取。每種情境保留 3 組對照,所以共有 15 組。每種的弱點對照都觀察到固定探針執行,其餘 10 組沒有觀察到本次探針執行。
但我沒有把後 10 組寫成單一的「安全」。它們仍分成反射但未執行、未反射、以文字呈現、頁面未使用來源、儲存後跳脫顯示,以及提交被拒絕等原因。工作台保留當天的 tool_verdict,另外提供跨情境的標準化結果;後者是為了整理,不會覆蓋前者。
6 份表單則分別來自 Day 16 與 Day 18:3 條 POST 反射路徑使用 q 欄位,3 條儲存後讀取路徑使用 message 欄位。這是對保存 HTML 的離線盤點,不是全站爬取,也不會代替當天的 POST 與後續 GET 證據。
頁面開頭先顯示產品名稱、版本與範圍,然後用 4 張摘要卡分別列出情境、案例、已觀察執行與作者核對數量。下方的發布關卡只顯示本次真正通過的條件;接著才是 6 條候選表單路徑,與 5 個情境各自的案例表。每個案例同時顯示組別、原始分類、標準化結果、是否觀察到固定探針執行,以及 AI 報告重驗狀態。
我沒有把所有證據內容都擠進一張表。如果我需要查某組回應 SHA-256、驗證器檔案或報告 artifact,應該讀 evidence-bundle.json;如果要做版本比較或在文字環境閱讀,則使用 report.md。dashboard 是導覽層,不是將底層證據疊成華麗圖表後取代原檔。頁尾仍保留 4 條解讀限制,避免使用者看到通過標記就把它當成正式風險評級。
index.html 是一份可直接開啟的靜態 dashboard。它把關鍵數量、發布關卡、6 條表單路徑、5 種情境的 15 組結果與解讀限制排在同一頁。樣式全部在檔案內,不讀取 CDN、字型或外部影像;頁面也沒有 <script>,所以開啟報告不需要執行 JavaScript。
頁面在 <head> 開頭就放入 CSP,主要限制是 default-src 'none'、script-src 'none'、img-src 'none'、object-src 'none'、base-uri 'none' 與 form-action 'none'。因為它是單檔靜態頁面,所以只以 style-src 'unsafe-inline' 保留檔內 CSS。
這個作品的責任邊界沒有因為 dashboard 完成而擴張。它不連線掃描正式網站、不送出新探針、不重新呼叫 AI,也不根據 15 組受控實驗為其他輸入背書。AI 報告的 revalidated 只表示現行結構、引用與分類規則通過;作者核對則是另一份可追溯紀錄,兩者沒有被壓成一個綠色勾勾。
「已完成」也不表示這份作品要永遠停在原地。這只代表 1.0.0 候選版的承諾不再移動:讀取哪些來源、如何重驗、產生哪 4 份檔案與哪些結論不能推導,都已寫進設定、程式與文件。未來若要支援第 6 種情境或真實網站,那會是新的威脅模型、新的證據合約與新一輪驗收,不應被塞進今天的「完成」之中。
今天我可以明確說,作品的功能範圍已完成:它能從已保存證據重建一致的 JSON、Markdown 與靜態 HTML,用 manifest 連結這些輸出,並在不一致時停下來。今天之後停止加功能;明天只做整體驗收,將可重現性與篡改偵測真正跑完,再決定是否凍結 v1.0。
那就…
明天見!