MAS-SZZ 論文閱讀分析:很多漏洞回溯真正失手的,不是 git 不夠會追,而是一開始就追錯行

本文由 AI 產生、整理與撰寫。

論文基本資訊

  • 論文標題:MAS-SZZ: Multi-Agentic SZZ Algorithm for Vulnerability-Inducing Commit Identification
  • 作者:Sicong Cao、Jinxuan Xu、Le Yu、Jing Yang、Xingwei Lin、Linlin Zhu、Fu Xiao
  • 年份:2026
  • 來源:arXiv:2604.24398
  • 論文連結:https://arxiv.org/abs/2604.24398
  • DOI:10.48550/arXiv.2604.24398
  • 主題:AppSec、Vulnerability Research、Code History Analysis、LLM Agents、Software Supply Chain、Secure Maintenance

很多團隊在看 CVE patch 時,第一反應都是「修掉了就好」;但真正麻煩的問題其實是:到底哪一個 commit 才是把漏洞第一次帶進來的那一刀?

這件事看起來像維護細節,實際上卻直接影響:

  • 哪些版本真的受影響
  • 漏洞檢測模型該學哪段程式碼
  • SBOM / VEX / 修補建議到底要回溯到哪裡
  • 開發團隊怎麼理解漏洞是怎麼長出來的

這篇 MAS-SZZ 值得看的地方,不是它又把 agent 塞進一個什麼都能加 agent 的場景,而是它抓到現有 SZZ 類方法的兩個老毛病:

很多漏洞 commit 回溯工具真正失手的,不是 git 歷史不夠長,而是一開始就追錯行,後面再怎麼回溯都只是把錯誤走得更遠。

所以這篇的核心 framing,不是「讓 LLM 幫你猜哪個 commit 看起來可疑」,而是把整件事拆成三段:

  • 先把漏洞根因講清楚,而且要附證據
  • 再從 patch hunk 裡挑出真正和漏洞有關的 anchor statement
  • 最後才沿 commit history 一步步往回走,直到找到最早仍含漏洞的版本

這篇在解什麼問題?

SZZ 類演算法的基本想法很直白:從 vulnerability-fixing commit(VFC)往回追,找出 vulnerability-inducing commit(VIC)。問題是,真實世界的修補 commit 很少只有一件事。

同一個 patch 裡常常混著:

  • 真正修漏洞的改動
  • 順手重構
  • 測試補強
  • 格式整理
  • 其他與安全無關的邏輯調整

如果你把所有 diff 都當成同等重要,回溯很容易被帶去錯的地方。作者把這個問題說得很清楚:既有方法常栽在兩件事上。

  • Challenge 1:anchor 選錯。 只盯 deleted / modified lines 很容易被 composite commits、ghost commits 或隱藏在未修改上下文裡的真正 root cause 騙過。
  • Challenge 2:backtracking 不夠聰明。 一步回溯太短,多步回溯如果只靠 line similarity 又會 over-trace 或 under-trace。

作者點名的現況也很殘酷:先前 SOTA 的 LLM4SZZ 在人工標註資料集上 accuracy 也只有 40.7%,離可以放心拿去做實務決策還差很遠。

MAS-SZZ 怎麼做?三段式 agent workflow

MAS-SZZ 不把 LLM 當成一個萬能判官,而是拆成幾個責任比較清楚的 agent,讓它們各自做不同判斷。

1. Evidence-Grounded Root Cause Analysis

第一步不是直接追 blame,而是先把漏洞根因寫清楚。MAS-SZZ 會把 CVE 描述、fixing commit 訊息、code diff 一起丟進流程,先由 Auditor 產出根因摘要與對應證據,再交給 Judge 檢查兩件事:

  • Evidence Traceability: 每個說法能不能回指到 CVE 或 patch 裡的具體證據
  • Logical Consistency: 根因敘述和 commit message 的修補意圖是否一致

這個設計的價值很實際。它不是先問模型「你覺得哪裡有洞」,而是先要求它把後續所有回溯判斷綁在同一份可檢查的 root-cause framing 上。

2. Intent-Driven Anchor Statement Selection

第二步是這篇最關鍵的地方之一:不是所有 patch hunk 都值得拿來回溯。

Reviewer 會先看每個 patch hunk 的語意與上下文,透過 step-forward prompting 分四步理解:

  1. 程式碼到底改了什麼
  2. 它怎麼改變執行時行為
  3. 開發者意圖是 fix、refactor、chore 還是別的
  4. 最後把這段改動壓成結構化 intent

接著 Evaluator 只保留和漏洞根因真正對得上的 hunk,再由 Locator 在這些 hunk 裡挑出最能代表 root cause 的 statement 當 anchor。

這個設計其實很像在對 diff 做去雜訊:先把「補測試」「整理碼風」「順手調整」這些不該主導回溯方向的東西剝掉,再拿真正會影響漏洞存在與否的那條線往回追。

3. Autonomous Repository Exploration

最後才輪到回溯。Tracer agent 不是像傳統方法那樣只退一步,或一路退到底,而是帶著前面整理出的 root cause 與 anchor statement,逐步檢查每個祖先 commit 裡漏洞是否仍存在。

它用的 stopping logic 也比較合理:當目前 commit 已經看不出漏洞,但前一版還看得出來,就回傳最後一個仍含漏洞的 commit 當 VIC。

換句話說,它真正在做的不是 line ancestry,而是 vulnerability presence judgment。這比單靠 diff 相似度更接近人類安全工程師真的會怎麼判斷。

論文裡的示範案例:問題不一定在 patch 最醒目的地方

作者拿 CVE-2018-1322 當 running example。這個案例裡,Apache Syncope 修補 commit 橫跨五個檔案,但人工標註的真正 VIC 其實集中在 SearchableFields.java 的單一 statement。

這正好說明這篇的核心主張:如果你不先搞清楚哪一段改動真的在修漏洞,而只是把整份 patch 當作回溯入口,最後很容易追到錯的人。

論文也提到在這個例子裡,先前的 V-SZZ 會因為 line similarity 掉下門檻而提早停下來;但 MAS-SZZ 會繼續往前追,因為它判斷的不是「這行長得還像不像」,而是「漏洞條件是否仍然存在」。

實驗怎麼做?

作者用了兩組人工驗證資料:

  • V-SZZ dataset:包含 100 個 C/C++69 個 Java 案例
  • Java-SZZ dataset:包含 100 個 Java VIC

比較對象共有七種既有方法:

  • B-SZZ
  • AG-SZZ
  • L-SZZ
  • R-SZZ
  • MA-SZZ
  • V-SZZ
  • LLM4SZZ

評估指標是標準的 Precision / Recall / F1-score

最值得記住的結果

先看 backbone selection。作者試了 GPT-4o-mini、GPT-5-mini、Gemini-3-flash、GPT-5.1、Gemini-3.1-pro、Claude-sonnet-4-6、DeepSeek-V3.2、Qwen3.5-plus。整體來看,重模型普遍比輕模型穩,其中 Gemini-3.1-pro 是作者最後選來做正式比較的 backbone。

V-SZZ-c 上,Gemini-3.1-pro 的成績是:

  • Precision = 0.73
  • Recall = 0.75
  • F1 = 0.74

正式和 baseline 比較時,MAS-SZZ 在三個資料切分上都拿到最佳或接近最佳的 recall 與 F1 trade-off

  • V-SZZ-c:0.73 / 0.75 / 0.74
  • V-SZZ-j:0.67 / 0.51 / 0.58
  • Java-SZZ:0.33 / 0.45 / 0.38

作者總結的關鍵數字是:相對於各資料集上最佳 baseline,MAS-SZZ 的 F1 分別提升了 4.22%1.75%65.22%

這裡最有意思的不是它把 precision 拉到誇張高,而是它做出一個比較能用的平衡。像 V-SZZ 在 V-SZZ-c 上 precision 高到 0.95,但 recall 只有 0.57;換句話說,它很保守,但會漏掉不少真正該追到的 VIC。MAS-SZZ 則是用 0.73 precision / 0.75 recall 拿到更平衡的 F1。

對實務來說,這通常比「極高 precision 但漏很多」更有價值,因為版本受影響分析最怕的,不只是多抓幾個 commit,而是把真正引洞的 commit 直接漏掉。

Ablation study 透露了真正有效的是哪兩件事

這篇另一個值得看的地方,是它沒有只停在「multi-agent 很強」,而是有拆掉元件驗證。

作者發現兩個設計都很重要:

  • 拿掉 intent-oriented anchor selection 後,三個資料集上的 precision 分別下降 8.96%59.52%3.12%
  • 拿掉 autonomous backtracking 後,MAS-SZZ 相對 vanilla 版本的 F1 優勢分別是 54.17%20.83%8.57%

這幾個數字很有說服力,因為它們剛好對應這篇開頭點出的兩個核心痛點:

  • anchor 選錯,回溯就從錯的地方開始
  • 回溯策略太死,追歷史時就會提早停或一路追歪

我怎麼看這篇?

我覺得 MAS-SZZ 最有價值的,不是它把「agent」這個詞放進一個傳統軟體工程問題,而是它把漏洞回溯這件事從純 diff heuristics,推向比較接近語意根因分析 + 證據導向歷史判斷的流程。

這件事為什麼重要?因為很多安全流程表面上是在做 code mining,實際上是在做決策支援:

  • 要不要把某版本列入受影響清單
  • 這個 patch 是在補根因,還是在補症狀
  • 漏洞資料庫裡哪個 commit 應該當 ground truth

如果底層工具只是盯著行號與相似度跑,那你得到的常常是很像答案的歷史噪音;MAS-SZZ 比較像是在問:「這個漏洞在這個 commit 當時,語意上到底還存不存在?」

這個方向我認為是對的,而且很適合未來接到:

  • vulnerability management pipeline
  • patch triage
  • affected-version inference
  • 訓練漏洞資料集自動標註

當然,這篇也還不是終點。它仍然依賴 CVE 描述品質、commit message 可讀性,以及 repository context 能不能被工具順利展開。遇到非常髒、非常碎、非常缺上下文的真實專案時,效果能不能維持,還有待後續觀察。

但至少它已經把方向講對了:

很多漏洞歷史分析真正缺的,不是再把 blame 跑快一點,而是先讓系統知道自己到底在追哪個漏洞根因。

結語

MAS-SZZ 這篇論文最值得記住的,不是它用 multi-agent 包裝了一個老問題,而是它把 VIC identification 重新定義成一個更像安全分析、而不只是版本控制技巧的任務:先證據化地理解 root cause,再語意化地挑 anchor,最後根據漏洞是否仍存在來決定何時停止回溯。

如果你在做 AppSec、漏洞資料工程、CVE triage、版本受影響分析,或任何需要把「補這個洞的 patch」往前還原成「最早哪次 commit 把洞放進來」的工作,這篇很值得讀。因為它提醒我們:真正該被追的,不是最像祖先的那一行,而是最早讓漏洞條件成立的那個歷史瞬間。

You may also like