本文所有資料皆為合成資料。主機名、IP、公司名、時間、事件經過全部虛構;CVE 編號使用真實公開漏洞,但受影響資產為虛構。
XDR / SIEM 平台匯出的一筆 case,實際上可能有上百個欄位、多層巢狀、還帶著平台自己的內部識別碼。長這樣(大幅簡化過的合成範例):
{
"case_id": "CASE-2026-0731-0042",
"tenant_id": "t_9f3a2b",
"created_ts": 1785312840,
"updated_ts": 1785316200,
"severity_raw": 4,
"status": "open",
"assignee": null,
"alerts": [
{
"alert_id": "ALT-88213",
"rule_id": "R-1042",
"rule_name": "Suspicious PowerShell Encoded Command",
"ts": 1785312840,
"endpoint": {"hostname": "TW-FIN-WS-014", "ip": "10.42.7.51", "os": "Windows 11 23H2"},
"process": {"name": "powershell.exe", "cmdline": "powershell -enc SQBFAFgA...", "parent": "outlook.exe"},
"mitre": ["T1059.001", "T1566.001"]
},
{
"alert_id": "ALT-88219",
"rule_id": "R-2210",
"rule_name": "Outbound Connection to Low-Reputation Host",
"ts": 1785313920,
"endpoint": {"hostname": "TW-FIN-WS-014", "ip": "10.42.7.51"},
"network": {"dst_ip": "203.0.113.77", "dst_port": 443, "bytes_out": 184320},
"mitre": ["T1071.001"]
}
],
"raw_telemetry_ref": "s3://...",
"_internal_score": 0.83,
"_model_version": "det-4.2.1"
}
如果你把這整包丟給模型說「寫一份報告」,會發生四件事:
_internal_score: 0.83 寫進報告,說「本事件風險評分 0.83」——那是平台內部的偵測信心分數,不是風險評分,客戶會誤解severity_raw: 4 直接翻成「嚴重性 4」,但你們對客戶用的是「高/中/低」三級在原始資料與模型之間插一層確定性的組裝程序,產出一個乾淨、完整、語意明確的資料包。模型只看資料包。
Data Pack 的結構(合成範例):
{
"pack_version": "1.0",
"incident": {
"ref": "IR-2026-0731-014",
"client_display_name": "【客戶名稱】",
"detected_at_local": "2026-07-31 14:14 (UTC+8)",
"duration_minutes": 56,
"severity": "高",
"severity_basis": "涉及使用者端點的可疑執行行為,並觀察到後續對外連線"
},
"affected_assets": [
{
"hostname": "TW-FIN-WS-014",
"asset_class": "使用者工作站",
"business_owner_dept": "財務部",
"criticality": "中",
"os": "Windows 11 23H2"
}
],
"timeline": [
{
"seq": 1,
"time_local": "14:14",
"event": "偵測到經過編碼的 PowerShell 指令執行",
"parent_process": "outlook.exe",
"technique": {"id": "T1059.001", "name": "命令與指令碼直譯器:PowerShell"},
"source_rule": "Suspicious PowerShell Encoded Command"
},
{
"seq": 2,
"time_local": "14:32",
"event": "同一端點對低信譽外部主機建立連線",
"destination": "203.0.113.77:443",
"bytes_out": 184320,
"technique": {"id": "T1071.001", "name": "應用層協定:Web 協定"},
"source_rule": "Outbound Connection to Low-Reputation Host"
}
],
"technique_summary": [
{"id": "T1566.001", "name": "網路釣魚:附件", "tactic": "初始存取", "confidence": "推測"},
{"id": "T1059.001", "name": "PowerShell", "tactic": "執行", "confidence": "已觀察"},
{"id": "T1071.001", "name": "Web 協定", "tactic": "命令與控制", "confidence": "已觀察"}
],
"related_cves": [],
"ioc": [
{"type": "ip", "value": "203.0.113.77", "reputation": "低信譽", "source": "威脅情報比對"}
],
"client_preferences": {
"severity_scale": "三級(高/中/低)",
"avoid_abbreviations": true,
"recommendation_split": ["立即", "中長期"]
},
"provenance": {
"source_case_id": "CASE-2026-0731-0042",
"assembled_at": "2026-07-31 15:10",
"assembled_by": "datapack-builder v1.0"
}
}
一、語意明確,沒有任何需要猜的欄位。 severity_raw: 4 變成 severity: "高",而且附上 severity_basis 說明依據。模型不需要知道映射規則,它只需要照著寫。
二、時間全部本地化並排序。 Unix timestamp 換成本地時間,事件按 seq 排好。時間差(duration_minutes)由程式算,不讓模型算。
三、技術編號一律附上名稱與戰術階段。 T1059.001 對模型是一串沒意義的字元。展開成名稱、戰術階段、以及信心程度(已觀察 vs 推測)。最後那項很重要——它讓模型知道哪些可以斷言、哪些要用推測語氣。
四、資產帶上業務脈絡。 asset_class、business_owner_dept、criticality 這些欄位不在原始 case 裡,是從資產清單(CMDB)查來的。這是報告能不能寫出「業務影響」的關鍵。 沒有它,模型只能寫「某台主機」;有了它,才能寫「財務部使用的工作站」。
五、客戶偏好內嵌。 Day 15 提過的客戶怪癖,直接放在 Data Pack 裡。模型每次都看得到。
六、Provenance 必填。 來源 case id、組裝時間、組裝程式版本。這是 Day 25「事實必回溯」與 Day 24 稽核軌跡的基礎。任何一份報告都要能回推到它是從哪一筆原始資料、用哪一版程式產生的。
注意 related_cves 是空陣列。這個案例沒有關聯到已知漏洞。
空欄位絕對不能省略。 如果你的組裝程式在沒有資料時直接不輸出那個欄位,模型會不知道是「沒有」還是「沒查」。明確地給一個空陣列,並且在 prompt 裡規定「空陣列代表已查詢但無結果」。
我踩過這個坑:某次報告漏了漏洞關聯段落,追查半天才發現是欄位沒輸出,模型以為那個主題不存在。
當初做這層是為了報告品質,但它後來帶來三個沒預期的好處:
一、可測試。 Data Pack 是純函式的輸出——同樣的 case 進去,同樣的 pack 出來。可以寫單元測試,可以回歸驗證。而模型的輸出沒辦法這樣測。
二、可換模型。 換掉底層模型時,Data Pack 完全不用動。這是 Day 29 那句「模型可換」的具體實現。
三、可審計。 審核者如果覺得報告哪裡怪,可以直接看 Data Pack——是資料錯了還是模型寫錯了,一眼就分得出來。
明天用這個 Data Pack 實際產一份報告。
🛡️ Instagram: @aid3fend — AI 資安實戰紀錄,歡迎追蹤交流。