第三方元件風險:歷次比較(Source Scan Diff)
功能群:第三方元件風險|配對鍵與資料模型先讀 功能群總覽
事實基準:2026-10-11 從 FE src/views/source-scan/SourceScanDiff.vue、src/components/source-scan/DiffFindingTable.vue、BE api/source_scan/routes/target_route.py::SourceScanTargetDiffRoute、jedi-source-scan source_scan_diff_service.py 實查掃出
變更紀錄
| 日期 |
FR |
變更 |
| 2026-10-11 |
FR-134 |
新頁:同一受評系統任選兩次完成的掃描比較已修補/新增/仍存在與元件版本異動;匯出回訪報告 |
1. 功能描述
同一套受評系統的兩次掃描放在一起看:上次之後修好了哪些、多了哪些、哪些還在。用在顧問回訪——客戶說「上次那批都處理了」,這頁直接回答處理了幾筆、還剩幾筆、有沒有新冒出來的。預設比最近兩次。
主要使用者:顧問、稽核員。
角色速覽
| 角色 |
一句話 |
持 detection.source-scan.read |
看比較 |
另持 detection.source-scan.export |
匯出回訪報告 |
1.1 功能總覽(本頁全部功能)
| # |
功能 |
說明 |
位置 |
詳述 |
| 1 |
選兩次掃描 |
「前次」「本次」兩個下拉,選項是這套系統所有完成的掃描(時間+檔名);預設最近兩次 |
頁首下方 |
§10 |
| 2 |
配對規則說明 |
固定一行說明配對方式 |
下拉下方 |
UC-SSD-01 |
| 3 |
三個數字 |
已修補/新增/仍存在 |
主區上方 |
§5 |
| 4 |
分類清單 |
四個頁籤:已修補、新增、仍存在、元件版本異動 |
主區 |
§5 |
| 5 |
開兩邊結果頁 |
「檢視前次結果」「檢視本次結果」 |
主區下方 |
掃描結果頁 |
| 6 |
匯出回訪報告 |
以本次掃描為主體產出報表,附「與上次掃描比較」一節 |
頁首右 |
UC-SSD-02 |
2. Use Case
UC-SSD-01 比較兩次掃描
| 項目 |
內容 |
| 角色 |
持 read |
| 前置條件 |
該系統至少兩次完成的掃描(不足顯示「尚無法比較」並提示由清單重新掃描) |
| 產出 / 後置條件 |
無寫入;結果即時算、不落表 |

配對規則:以「生態系+套件名稱+弱點編號」配對,不比對版本(fingerprint)。套件升了版但仍受同一弱點影響者列為「仍存在」,不會被算成「修掉一筆、又新增一筆」。
| 分類 |
定義 |
版本欄 |
| 已修補 |
前次有、本次沒有 |
前次版本 |
| 新增 |
前次沒有、本次有 |
本次版本 |
| 仍存在 |
兩次都有 |
兩邊版本;版本有變動的排前面——已升版但沒升到修正版 |
| 元件版本異動 |
元件以 purl 去版本配對,列出升降版、新增、移除 |
前次/本次版本,缺的一邊顯示「無此元件」 |
- 兩次掃描的先後依完成時間判定,後端一律把較早那次回成
scan_a;使用者把下拉選反了,畫面仍顯示「前次 → 本次」的正確方向。
- 選同一次時提示「請選擇兩次不同的掃描」,不送請求。
UC-SSD-02 匯出回訪報告
| 項目 |
內容 |
| 角色 |
持 export |
| 前置條件 |
已算出比較結果 |
| 產出 / 後置條件 |
下載一個檔;稽核事件 6192 |
與結果頁的匯出報表同一個對話框(格式、委託單位名稱),多帶 diff_with=較早那次的 uid。報表以較新那次為主體,章節同結果頁 UC-SSR-03,在「統計」之後多一節「與上次掃描比較」。
3. 權限矩陣
| 操作 |
FE 判定 |
BE 強制 |
BE 檢查位置 |
| 進頁、比較 |
路由守衛(source-scan-diff 子路由) |
require_license("plugin")+read |
SourceScanTargetDiffRoute.get |
| 匯出回訪報告 |
v-can=export |
export |
SourceScanExportRoute.post |
4. 狀態機與前置條件
| 條件 |
效果 |
出處 |
| 完成的掃描 < 2 |
顯示「尚無法比較」 |
SourceScanDiff.vue |
| 兩次不屬同一系統 |
400 SOURCE_SCAN_400011 |
source_scan_app_service.py::diff_scans |
| 任一次未完成 |
412 SOURCE_SCAN_412003 |
同上 |
| 系統不存在 |
404 SOURCE_SCAN_404001 |
同上 |
5. UI 設計

- 三個數字卡:已修補(左側綠條)、新增(橘條)、仍存在(灰條),手機寬度改直排。
- 分類頁籤欄位:套件、生態系、版本(依分類顯示前次/本次/兩邊)、弱點編號(連 NVD)、嚴重度、KEV 標記、修正版。每個頁籤頂端一行說明該分類的定義。
6. API 規格
6.1 總清單
| Method + Path |
說明 |
能力點 |
GET /source-scan/targets/{uid} |
標題 |
read |
GET /source-scan/targets/{uid}/scans |
下拉選項(過濾出 done) |
read |
GET /source-scan/targets/{uid}/diff?a=&b= |
比較 |
read |
POST /source-scan/scans/{uid}/export |
回訪報告(帶 diff_with) |
export |
6.2 比較回應(SourceScanDiffResponseSchema)
| 欄位 |
型別 |
說明 |
| scan_a / scan_b |
object |
uid、finished_at、source_ref;a 一律是較早那次 |
| counts |
object |
fixed、new、remaining、components_changed |
| fixed / new / remaining |
list |
每筆 fingerprint、vuln_id、package、ecosystem、severity、in_kev、version_a、version_b、fixed_versions、nvd_url |
| components_changed |
list |
每筆 ecosystem、name、version_a、version_b |
出處:api/source_scan/serializers/source_scan.py(_DiffFindingSchema、_ComponentChangeSchema、SourceScanDiffResponseSchema)。
7. 前端檔案地圖(compliance-manager-fe/)
| 檔案 |
角色 |
src/views/source-scan/SourceScanDiff.vue |
主頁:選兩次、三數字、四頁籤、匯出 |
src/components/source-scan/DiffFindingTable.vue |
已修補/新增/仍存在的清單 |
src/components/source-scan/ExportReportDialog.vue |
匯出對話框(帶 diffWith) |
8. 後端檔案地圖
| 鏈路 |
Route |
App Service |
底層 |
| 比較 |
target_route.py::SourceScanTargetDiffRoute |
source_scan_app_service.py::diff_scans |
source_scan_diff_service.py(純函式,不碰 DB) |
| 回訪報告 |
scan_route.py::SourceScanExportRoute |
report/report_export_service.py |
report_comparison.py、templates/report/_comparison.html、report_docx_comparison.py |
9. DB
只讀:compliance.source_scans、source_scan_findings(用 fingerprint)、source_scan_components(用 purl 去版本)。欄位卡見掃描結果頁 §9。
每次掃描完成時,背景工作也會用同一套比較對受評系統的上一次完成掃描算一次,存進 summary.delta(清單「前次比較」與結果頁「前次比較」區塊讀它)。本頁則是任選兩次、即時算。
10. 頁面邏輯與資料對應
- 載入:平行取受評系統與歷次掃描,過濾出 done(後端給新到舊)→ 「本次」預設最新、「前次」預設第二新。
- 兩個下拉任一變動即重算;選同一次不送請求。
- 匯出回訪報告用的主體掃描=
result.scan_b(較新那次)。
11. 背景行為與外部依賴
| 類型 |
內容 |
| 背景 |
無(即時算);summary.delta 由掃描背景工作在完成時寫入 |
| 稽核事件 |
6192 匯出 |
| socket |
無 |
12. 邊界情況與已知坑
- 配對不含版本是刻意的:用含版本的
match_key 會把「升版但沒修好」算成一修一增,數字好看但失真。
- 工具組合不同的兩次掃描:例如前次只跑兩家、本次跑三家,本次可能多出只有第三家報的弱點,會落在「新增」。比較前請留意兩次的工具設定。
- 來源類型固定:同一系統的歷次掃描來源類型相同(精靈鎖定),否則元件辨識範圍不同,比較失真。
13. 開發與驗證
- 導航:第三方元件風險 → 列上 🕘(完成兩次以上才出現)
- 驗收:同一系統先掃舊版鎖定檔、再掃升過版的鎖定檔 → 「已修補」有數字、「仍存在」裡版本變動的排前面、「元件版本異動」列出升版元件;匯出回訪報告有「與上次掃描比較」一節