第三方元件風險:掃描結果頁(Source Scan Result)
功能群:第三方元件風險|三套工具、summary 形狀、呈現原則先讀 功能群總覽
事實基準:2026-10-11 從 FE src/views/source-scan/SourceScanResult.vue、src/components/source-scan/*、BE api/source_scan/routes/scan_route.py、jedi-source-scan source_scan_app_service.py/report//ai_analysis_service.py、DEV compliance.source_scans/source_scan_findings 實查掃出
變更紀錄
| 日期 |
FR |
變更 |
| 2026-10-11 |
FR-134 |
新頁:風險總覽/弱點明細/元件清單三分頁、三家工具動態欄位與「顯示工具」勾選、各家編號與分數差異標示、單一完整報表匯出(PDF/HTML/Word)、AI 摘要分析 |
1. 功能描述
單次掃描的結果頁。兩個入口共用:清單的「檢視結果」、任務抽屜的「查看完整結果」都開這一頁。掃描還沒完成時只顯示四段進度並自動更新;完成後顯示三個分頁。
主要使用者:顧問、稽核員——看懂一套系統的第三方元件有哪些已知弱點、多嚴重、有沒有修正版,並匯出報表交付。
角色速覽
| 角色 |
一句話 |
持 detection.source-scan.read |
看結果、下載 SBOM 與原始結果、按 AI 摘要分析 |
另持 detection.source-scan.export |
多一顆「匯出報表」 |
1.1 功能總覽(本頁全部功能)
| # |
功能 |
說明 |
位置 |
詳述 |
| 1 |
頁首資訊 |
系統名稱(任務掃描沒有受評系統時顯示「第三方元件風險結果」)、掃描時間、輸入來源、上傳檔名 |
頁首 |
§5 |
| 2 |
弱點資料日期 |
Tag「弱點資料日期 YYYY-MM-DD」,依資料年齡上色 |
頁首右 |
UC-SSR-01 |
| 3 |
匯出報表 |
選格式(PDF/HTML/Word)、委託單位名稱(選填)下載 |
頁首右 |
UC-SSR-03 |
| 4 |
掃描中進度 |
未完成時只顯示四段進度+「掃描完成後將於此顯示結果,頁面會自動更新」,每 3 秒輪詢 |
主區 |
§10 |
| 5 |
風險總覽 |
嚴重度分布、KEV、EPSS、修補可行性、分析涵蓋度、前次比較、元件授權分布 |
第一分頁 |
§5.1 |
| 6 |
AI 摘要分析 |
按了才呼叫 AI 把統計整理成文字;可重新分析 |
風險總覽下方 |
UC-SSR-04 |
| 7 |
弱點明細 |
每弱點一列、各工具一欄;篩選、排序、分組、展開看描述與來源頁 |
第二分頁 |
UC-SSR-02 |
| 8 |
顯示工具 |
勾選要顯示哪幾家工具的欄;沒跑的工具灰掉 |
弱點明細篩選列 |
§5.2 |
| 9 |
元件清單 |
原始 SBOM 檔攤成表:可切格式、搜尋、每元件弱點數可點 |
第三分頁 |
§5.3 |
| 10 |
原始檔案與來源 |
下載各格式 SBOM、各工具原始結果;複製 SHA-256;工具版本與資料來源 |
元件清單下方 |
§5.3 |
2. Use Case
視覺慣例:判斷框=分支條件;紅框=擋下並標 error code;綠框=完成。
UC-SSR-01 判讀一次掃描
| 項目 |
內容 |
| 角色 |
持 read |
| 前置條件 |
掃描 done |
| 產出 / 後置條件 |
無寫入 |
建議閱讀順序(也是畫面的排列順序):
- 先看弱點資料日期:超過 30 天黃、超過 90 天紅(以掃描完成時間算,舊掃描看的是「當時用了多舊的資料」)。資料太舊會漏掉新公布的弱點。
- 再看分析涵蓋度:有生態系缺鎖定檔時,紅色警示「此專案 npm 部分缺少 package-lock.json,弱點明細僅涵蓋直接宣告的元件、版本為估算值,且無法分析傳遞相依,實際風險可能較高」。這行出現時,後面的數字都可能低估。
- KEV 與 EPSS:已被實際利用、或預估近期被利用機率高的弱點,列出前幾筆(超過列「僅列前 N 筆,共 M 筆」)。
- 嚴重度分布:三家工具各一欄、各自計數。
- 弱點明細:逐列看、比對各家判讀差異。
UC-SSR-02 在弱點明細找出要先處理的
| 項目 |
內容 |
| 角色 |
持 read |
| 前置條件 |
掃描 done |
| 產出 / 後置條件 |
無寫入;篩選與排序每次重新向後端查詢 |

- 嚴重度 chip:點了就篩,篩的是列層等級(各家中較高者),可多選。
- 排序:四種,表頭顯示「目前排序:KEV → EPSS → CVSS」。選中的鍵提到最前,其餘依 KEV→EPSS→CVSS 接在後面。
- 檢視:依套件分組(預設,每頁 100 筆減少一個套件被切兩頁;組頭顯示最高嚴重度、弱點數、KEV 數,被切頁時標「續上頁」「續下頁」)或依弱點逐列。
- 只看 KEV、只看有修正版:KEV 資料未載入時「只看 KEV」停用。
- 元件篩選:從元件清單點弱點數進來時,篩選列多一顆「元件:」,可清除。
- 展開列:弱點描述(工具沒給時「工具未提供描述」)、NVD 連結(非 CVE 編號時說明 NVD 無對應頁面)、各家「<工具> 來源頁」連結與編號、其他編號(別名)、套件識別(purl)。各家分級不一致時多一段說明「各家原始分級均保留於上方表格,請比對各工具來源頁內容」。
UC-SSR-03 匯出報表
| 項目 |
內容 |
| 角色 |
持 export |
| 前置條件 |
掃描 done(未完成 412 SOURCE_SCAN_412001) |
| 產出 / 後置條件 |
下載一個檔;稽核事件 6192 |

- 報表只有一種:完整技術版,含全部弱點與元件清單。顧問會自行消化再交付,不另提供摘要版或隱藏內部備註的版本。
- 對話框兩個欄位:檔案格式(PDF/HTML/Word)、委託單位名稱(選填,顯示於報表抬頭;預設帶系統名稱)。
- 檔名見總覽 §8 第 1 條,例如
PrimeVue_弱點掃描報告_20261011-1341.pdf。
- 報表不含 AI 摘要。
報表章節(HTML 與 PDF 同一份模板,Word 用 docx 範本同章節):
| 章節 |
內容 |
| 封面 |
標題、委託單位、受評系統、掃描時間、產生時間 |
| 統計 |
嚴重度分布(這次跑了的每家工具一欄;Word 改為一家一列)、元件數、弱點數 |
| 與上次掃描比較 |
只在回訪報告出現(見歷次比較) |
| 已知遭利用弱點(CISA KEV)/高利用機率弱點(EPSS 達門檻) |
清單 |
| 有修正版的弱點 |
清單 |
| 授權類型統計 |
Copyleft/寬鬆/未標示 |
| 全部弱點列表 |
每筆:各工具判讀、編號連 NVD、來源頁連結、修正版 |
| 元件清單 |
全部元件 |
| 附錄:工具版本、資料日期與原始報告指紋 |
各工具版本、弱點資料日期、各原始檔 SHA-256 |
| 資料來源說明 |
NVD/CVSS、CISA KEV、FIRST EPSS、各工具弱點資料庫 |
報表只寫事實句,不出現「屬高風險」「建議立即」這類結論。PDF 由同一份 HTML 經 WeasyPrint 產出,字型用主機的 Noto Sans CJK TC(缺字型時中文會整段消失,見 CLAUDE.md「主機層依賴」)。
UC-SSR-04 AI 摘要分析
| 項目 |
內容 |
| 角色 |
持 read |
| 前置條件 |
本租戶已設定 AI(沒設定時整張卡不顯示) |
| 產出 / 後置條件 |
source_scans.ai_analysis 寫入或覆蓋;扣 AI 額度、留呼叫紀錄 |
- 卡片說明「按下後才會呼叫 AI 並扣用 AI 額度,將上方統計彙整為文字說明;報表不含此段」。執行中顯示「AI 彙整中,約需十餘秒…」。
- 結果固定標「AI 生成,以上方統計為準」,下方註記產生者、時間、模型。再按「重新分析」覆蓋前一次。
- 送給 AI 的只有統計與前 20 筆弱點的事實欄位(編號、purl、等級、CVSS、KEV、EPSS、修正版),不送原始報告與弱點描述全文——描述來自外部弱點庫,是不可信文字。提示詞要求只整理資料段列出的事實、不下結論、不給燈號。
- 提示詞以 AI 守門規則目錄
prompts.yaml 的 source-scan.analysis 為準,套件內建一份逐字相同的退路。
- 錯誤:未設定 AI 412
SOURCE_SCAN_412002;額度用完 429 SOURCE_SCAN_429001;AI 失敗 502 SOURCE_SCAN_502001。
3. 權限矩陣
| 操作 |
FE 判定 |
BE 強制 |
BE 檢查位置 |
| 進頁、看三分頁 |
路由守衛(source-scan-result 子路由) |
require_license("plugin")+read |
SourceScanDetailRoute.get、SourceScanFindingsRoute.get、SourceScanComponentsRoute.get |
| 下載 SBOM/原始結果 |
— |
read |
SourceScanFileRoute.get |
| 匯出報表 |
v-can=export;且掃描 done |
export;未完成 412 |
SourceScanExportRoute.post |
| AI 摘要分析 |
後端回 ai_available=false 時整張卡不顯示 |
read;未設定 AI 412 |
SourceScanAiAnalysisRoute.post |
| 租戶歸屬 |
— |
RLS;別租戶的掃描 404 SOURCE_SCAN_404002 |
source_scan_app_service.py::_get |
任務掃描不另判專案成員:任務發起的掃描結果頁同樣只看 detection.source-scan.read。要加專案層守門須連「任務發起的掃描」頁籤一起改,另案處理。
4. 狀態機與前置條件
| 條件 |
效果 |
出處 |
status 為 queued/running |
只顯示四段進度並輪詢;匯出鈕不出現 |
SourceScanResult.vue isDone |
status 為 failed |
顯示四段進度停在失敗段與錯誤訊息 |
ScanStageProgress.vue |
summary.kev.available=false/epss.available=false |
對應區塊顯示「未載入」與原因,不顯示 0 |
FactThreatList.vue |
summary.coverage.missing_lock 非空 |
分析涵蓋度紅色警示 |
FactCoverage.vue |
| 本次沒跑某工具 |
該工具不出現在任何欄位;「顯示工具」勾選框灰掉 |
useScanToolsRan.js |
| 掃描完成時資料年齡 > 30/> 90 天 |
弱點資料日期 Tag 黃/紅 |
SourceScanResult.vue::vulndbAge |
5. UI 設計

5.1 風險總覽
| 區塊 |
內容 |
資料 |
| 嚴重度分布 |
等級 × 工具的計數表(Critical/High/Medium/Low/Negligible/未分級/合計),只列這次跑了的工具;各家分級不一致時底下一行「有 N 筆工具間分級不一致,詳見『弱點明細』」 |
summary.severity、tools_disagree |
| 已知遭利用弱點(CISA KEV) |
編號、套件、收錄日 |
summary.kev+findings in_kev=true |
| 高利用機率弱點(EPSS ≥ 10%) |
編號、套件、EPSS 機率 |
summary.epss(門檻 threshold,預設 0.1) |
| 修補可行性 |
已有修正版 N、尚無修正版 N、最早修正版發布日 |
summary.fixable |
| 分析涵蓋度 |
缺鎖定檔的生態系(點名檔名,如 npm → package-lock.json、pypi → poetry.lock);NTIA 最低要素 n/7 與缺哪幾項 |
summary.coverage |
| 前次比較 |
已修補/新增/仍存在;首次掃描顯示「首次掃描」 |
summary.delta |
| 元件授權分布 |
元件總數;Copyleft 類(GPL/LGPL/AGPL)、寬鬆類(MIT/Apache/BSD/ISC)、未標示或無法辨識 |
summary.components+components license_risk |
5.2 弱點明細
| 欄 |
內容 |
| 套件/版本 |
從 purl 解出名稱與版本 |
| 弱點編號 |
合併後的編號(CVE 優先),連 NVD |
| 每家工具一欄「<工具>(等級/CVSS)」 |
等級徽章(依工具分級上色)+分數;該家編號與合併編號不同時,下方小字列該家自己的編號(可點來源頁,一行截斷、滑過看全文);該家沒報顯示「未報」 |
| 不一致標示 |
跑了的工具之間等級不同(提示「工具間分級不一致」)或分數差 ≥ 0.1(提示「工具間分數不一致」);只比有跑的工具,不受「顯示工具」勾選影響 |
| KEV/EPSS |
「已列入」標記、EPSS 百分比 |
| 修正版 |
工具列出的修正版本 |
顯示工具:篩選列的「顯示工具」三個勾選框。純畫面篩選——收掉某家只是隱藏那欄,不重查、不影響筆數與風險總覽。本次沒跑的工具灰掉並提示「本次掃描未執行」;只剩一個勾時不能取消;換一筆掃描時重設為全勾。
各家差異為什麼要露出:實測三家對同一批弱點,等級幾乎一致,但編號寫法常不同(Trivy 多寫 CVE、Grype 多寫 GHSA)、分數偶有 0.1 的差。只秀等級時看起來三家一模一樣,顧問無從判斷各家是否真的看到同一件事。
5.3 元件清單
- 元件清單=原始 SBOM 檔攤成表,欄位照原檔,不另加工:元件名稱、版本、生態系、授權、PURL(點擊複製)、CPE、bom-ref(CycloneDX)或 SPDX ID(SPDX)。
- 格式切換:這次產出了哪幾種 SBOM 就有幾顆(SPDX 固定排前)。
- 搜尋:名稱或 PURL。
- 多一欄「弱點數」:依 purl 對上後端元件清單算好的數字,點了切到弱點明細並篩該元件。元件沒有 purl 時標「此元件不在弱點比對範圍」。
- 單檔超過 5,000 個元件時只列前 5,000 筆並提示,完整內容請下載。檔案解析不了時提示下載後以工具開啟。
原始檔案與來源(元件清單下方):
| 區 |
內容 |
| 軟體物料清單(SBOM) |
每種格式一列:下載、複製 SHA-256 |
| 工具原始報告 |
這次跑了的每家工具一份 JSON:下載、複製 SHA-256;沒產出顯示「此次掃描未產出此類檔案」 |
| 工具與資料來源 |
各工具版本、弱點資料日期、上傳檔名、上傳檔 SHA-256 |
6. API 規格
6.1 總清單(本頁呼叫)
| Method + Path |
說明 |
能力點 |
GET /source-scan/scans/{uid} |
掃描本體(狀態、進度、summary、產物清單、AI 摘要) |
read |
GET /source-scan/targets/{uid} |
取受評系統名稱當標題(任務掃描沒有) |
read |
GET /source-scan/scans/{uid}/findings |
弱點明細分頁 |
read |
GET /source-scan/scans/{uid}/components |
元件分頁(給弱點數、授權統計、KEV/EPSS 清單補套件名) |
read |
GET /source-scan/scans/{uid}/files/{kind} |
下載 SBOM 或原始結果 |
read |
POST /source-scan/scans/{uid}/export |
匯出報表 |
export |
POST /source-scan/scans/{uid}/ai-analysis |
AI 摘要分析,回整筆掃描 |
read |
GET /source-scan/targets/{uid}/scans |
判斷是否首次掃描(前次比較區塊) |
read |
6.2 掃描本體(SourceScanResponseSchema)
| 欄位 |
型別 |
說明 |
| uid / target_uid / detection_execution_uid |
string|null |
兩個入口二擇一非空 |
| source_type / source_ref |
string / dict |
source_ref.filename 是上傳檔名 |
| status |
string |
queued/running/done/failed |
| progress |
dict|null |
四段進度 |
| tools |
dict |
{"vuln": [...], "sbom_formats": [...]}——這次勾選 |
| tool_versions |
dict |
各工具版本 |
| vulndb_date |
date|null |
當次弱點資料日期 |
| summary |
dict|null |
見總覽 §6 |
| sbom_quality |
dict|null |
NTIA 要素與缺鎖定檔明細 |
| sbom_formats / raw_outputs / artifacts |
計算欄 |
產物清單(種類、格式鍵、檔名、SHA-256) |
| ai_analysis |
dict|null |
文字、模型、時間、產生者暱稱 |
| ai_available |
bool|null |
本租戶是否設定 AI |
| error / started_at / finished_at |
|
|
| 審計欄+暱稱 |
|
|
出處:api/source_scan/serializers/source_scan.py:88-131。
6.3 弱點明細查詢(SourceScanFindingQuerySchema)
| 參數 |
說明 |
| page / page_size |
分頁;page_size 上限見 serializer |
| sort |
kev|epss|cvss|severity|package;選中的鍵在前,其餘依 KEV→EPSS→CVSS |
| severity |
可重複,列層等級 |
| tool |
只看某家有報的 |
| in_kev / has_fix |
布林 |
| component_purl |
元件篩選 |
回應每列(SourceScanFindingSchema):
| 欄位 |
型別 |
說明 |
| uid / component_purl / vuln_id |
string |
|
| aliases |
list |
其他編號 |
| severity / cvss_score |
string / float |
列層:各家最高 |
| trivy / grype / osv |
dict|null |
各家判讀 {reported, id, severity, score, advisory_url};沒跑或沒報為 null |
| fixed_versions / oldest_fix_date |
list / date |
|
| in_kev / kev_date_added / epss_score |
|
|
| description / nvd_url |
string |
|
| package_group |
dict|null |
分組模式的組頭資訊 |
6.4 下載(GET /files/{kind})
kind=sbom|trivy|grype|osv;sbom 另帶 ?format=cyclonedx|spdx|cyclonedx-json…&version=1.6。檔案這次沒產出 404 SOURCE_SCAN_404003。標頭規則見總覽 §8 第 2 條。
6.5 匯出(SourceScanExportRequestSchema)
{
"format": "pdf",
"client_name": "委託單位 A",
"diff_with": null
}
| 欄位 |
說明 |
| format |
必填,html|pdf|docx |
| client_name |
選填,≤255,封面委託單位 |
| diff_with |
選填,同系統另一次已完成掃描的 uid;帶了就是回訪報告(多「與上次掃描比較」一節) |
7. 前端檔案地圖(compliance-manager-fe/)
| 檔案 |
角色 |
src/views/source-scan/SourceScanResult.vue |
主頁:頁首、三分頁、輪詢 |
src/components/source-scan/FactDashboard.vue |
風險總覽七區塊 |
src/components/source-scan/FactSeverity.vue/FactThreatList.vue/FactCoverage.vue/FactCard.vue |
風險總覽子區塊 |
src/components/source-scan/AiAnalysisCard.vue |
AI 摘要分析 |
src/components/source-scan/FindingsTable.vue/FindingsFilterBar.vue |
弱點明細表與篩選列 |
src/components/source-scan/FindingToolCell.vue/FindingDetail.vue/FindingGroupHeader.vue |
工具格子、展開列、分組組頭 |
src/components/source-scan/SbomViewer.vue/RawDownloads.vue |
元件清單、原始檔案與來源 |
src/components/source-scan/ExportReportDialog.vue |
匯出對話框 |
src/composables/useScanToolsRan.js |
這次跑了哪幾家(勾選 ∩ summary 非 null,依 SCAN_TOOLS 順序) |
src/composables/useSourceScanFacts.js/useSourceScanFindings.js/useSbomViewer.js/useScanFileDownload.js |
資料取用 |
8. 後端檔案地圖
| 鏈路 |
Route |
App Service |
底層 |
| 掃描本體/明細/元件 |
api/source_scan/routes/scan_route.py |
jedi-source-scan source_scan_app_service.py |
domain/source_scan、infra/source_scan |
| 下載 |
scan_route.py::SourceScanFileRoute、_file_response |
scan_file_download.py::pick_file |
宿主檔案庫 adapter |
| 匯出 |
scan_route.py::SourceScanExportRoute |
report/report_export_service.py |
report_model.py、report_render.py(HTML/PDF)、report_docx*.py(Word)、templates/report/ |
| AI 摘要 |
scan_route.py::SourceScanAiAnalysisRoute |
ai_analysis_service.py |
宿主 AI 閘道(FR-122) |
| 檔名 |
— |
artifact_names.py |
— |
9. DB
9.1 資料表總清單
| 表 |
讀/寫 |
說明 |
| compliance.source_scans |
讀;AI 摘要寫 ai_analysis |
掃描本體 |
| compliance.source_scan_findings |
讀 |
弱點明細 |
| compliance.source_scan_components |
讀 |
元件、授權 |
| compliance.source_scan_targets |
讀 |
標題 |
| public.upload_files |
讀 |
SBOM、原始結果、報表檔 |
9.2 compliance.source_scans
| 欄位 |
型別 |
說明 |
| id / uid |
bigint / uuid NOT NULL |
|
| tenant_id / org_unit_id |
bigint |
|
| target_uid |
uuid |
可空:從檢測工具派工進來的掃描不掛受評系統 |
| detection_execution_uid |
varchar(36) |
soft-ref → detection_executions.uid;非空表示跑完要回寫檢測結果 |
| source_type |
varchar(16) NOT NULL |
|
| source_ref |
jsonb |
|
| input_file_id |
bigint |
soft-ref → upload_files.id(上傳的源碼包或 SBOM 檔) |
| status |
varchar(16) NOT NULL |
|
| background_job_uid |
varchar(36) |
|
| tools / tool_versions |
jsonb |
|
| vulndb_date |
date |
當次使用的弱點資料庫日期(結果頁顯示新舊) |
| summary / sbom_quality |
jsonb |
|
| raw_outputs / sbom_files |
jsonb |
產物檔指標與 SHA-256 |
| report_file_id |
bigint |
soft-ref → upload_files.id |
| ai_analysis |
jsonb |
|
| error |
text |
|
| started_at / finished_at |
timestamptz |
|
| 審計欄 |
|
|
9.3 compliance.source_scan_findings
| 欄位 |
型別 |
說明 |
| scan_uid |
uuid NOT NULL |
→ source_scans.uid cascade |
| component_purl |
text |
|
| vuln_id |
varchar(128) NOT NULL |
合併編號,CVE 優先 |
| aliases |
jsonb |
|
| severity / cvss_score |
varchar(16) / numeric(4,1) |
列層 |
| trivy / grype / osv |
jsonb |
各家判讀;沒跑或沒報為 NULL |
| fixed_versions / oldest_fix_date |
jsonb / date |
|
| in_kev / kev_date_added / epss_score |
boolean NOT NULL / date / numeric(6,5) |
|
| match_key |
text |
ecosystem+name+version+正規化弱點編號(跨工具配對) |
| fingerprint |
text |
ecosystem+name+正規化弱點編號,不含版本——升版仍受影響要算「仍存在」 |
| description / nvd_url |
text |
|
9.4 compliance.source_scan_components
| 欄位 |
型別 |
說明 |
| scan_uid |
uuid NOT NULL |
|
| purl |
text |
|
| name |
varchar(512) NOT NULL |
|
| version / ecosystem |
varchar |
|
| licenses |
jsonb |
|
| license_risk |
varchar(16) |
copyleft|permissive|unknown |
10. 頁面邏輯與資料對應
- 載入:
GET /scans/{uid};有 target_uid 再 GET /targets/{uid} 取標題(取不到退回預設標題)。未完成時每 3 秒重取,完成才載分頁——未完成的摘要是空的,顯示會誤導。
- 跑了哪幾家:
useScanToolsRan = tools.vuln 與 summary.severity 非 null 的交集,依 ['trivy','grype','osv'] 排序;所有欄位與統計都吃它。
- 元件清單點弱點數:切到弱點明細分頁,呼叫
FindingsTable.showComponent(purl) 加元件篩選。
- 下載:前端讀
X-Filename 並 decodeURIComponent 當存檔名;讀不到才用 fallback。
- 錯誤:全域 interceptor 依 error_code 顯示。
11. 背景行為與外部依賴
| 類型 |
內容 |
| AI 閘道 |
FR-122:provider 設定、額度、呼叫紀錄、Prompt Guard |
| PDF |
WeasyPrint,主機字型 Noto Sans CJK TC |
| Word |
docxtpl 範本 templates/report/report.docx,由 scripts/generate_source_scan_docx_template.py 產生 |
| 稽核事件 |
6192 匯出 |
| socket |
無;未完成時輪詢 |
12. 邊界情況與已知坑
- 只跑兩家的舊掃描:
osv 欄為 NULL、tools.vuln 只有兩家,畫面照樣兩欄,不可因欄位缺就壞。
- 只勾部分工具的掃描:沒勾的那家
summary.severity 為 null、原始結果下載 404。任務掃描沿用建任務時的工具設定,可能因此沒有 OSV。
- 分級一致不代表三家看到同一件事:編號寫法、來源頁、分數都可能不同,工具格子會把差異顯示出來。
- 任務掃描結果頁沒有歷次比較:任務掃描不掛受評系統。
- PDF 中文消失:主機缺
fonts-noto-cjk 時發生,非程式問題。
13. 開發與驗證
- 導航:第三方元件風險 → 列上 📊;或任務抽屜「查看完整結果」
- 驗收:三家全勾掃一包 → 弱點明細三欄、嚴重度三欄、展開列三個來源頁、原始檔多一份 OSV;取消「顯示工具」的 Grype → 欄位收掉、筆數不變;匯出三種格式檔名中文正確;開一筆只跑兩家的舊掃描 → 兩欄不報錯
- 測試資料:DEV 弱點資料在
/opt/vulndb;測試帳號密碼見 .env/部署文件