來自以太坊基金會協定安全團隊的筆記,內容關於針對真實協定程式碼執行協同 AI 代理,包含我們如何組織工作、哪些內容經得起審查,以及客戶端團隊與安全研究人員能從中學到什麼。本文為獨立篇章;後續文章將深入探討個別客戶端。
我們執行了什麼,以及令我們驚訝的事
在以太坊基金會的協定安全團隊中,我們一直針對網路所依賴的系統(如系統軟體、密碼學程式碼以及必須正確無誤的合約)執行協同 AI 代理。這些代理發現了真實的錯誤。其中一個現已公開:在 libp2p 的 gossipsub 中一個可遠端觸發的恐慌(panic),這是以太坊共識客戶端運行的點對點層的核心部分,該錯誤已修復並披露為 CVE-2026-34219,並歸功於該團隊。
代理發現錯誤並不令人驚訝。令人驚訝的是,用於發現錯誤的工作量如此之少,而用於分辨真實錯誤與看似真實的錯誤的工作量卻如此之大。
本文寫給希望進行相同工作的客戶端團隊與安全研究人員。內容涵蓋我們如何組織代理、候選項目被視為正式發現前必須達到的標準,以及保持結果可信的習慣。
其他地方的團隊也正趨向於相同的做法。Anthropic 的邊境紅隊(Frontier Red Team)建立了一個代理,該代理編寫基於屬性的測試,並在整個 Python 生態系統中發現了真實的錯誤。Cloudflare 透過安全研究測試框架執行了一個邊境模型來針對他們自己的系統。每個人都落入相同的迴圈:將強大的模型指向程式碼庫,讓它搜尋,並對回傳的結果進行分類。因此,真正的問題在於如何做到這一點,而不會淹沒在聽起來自信滿滿的雜訊中。
首先要提醒一點:代理驅動的稽核工具發展迅速,任何特定的設定在幾週內就會過時。因此,本文刻意著重於持久的方法,而非工具。漏洞披露本身就是一個獨立的主題,可能會另外寫成一篇文章。
代理是搜尋工具,而非預言機
指向程式碼庫的代理是一種搜尋工具,非常類似於模糊測試工具(fuzzer)。不同之處在於回傳的內容。模糊測試工具會交給你一個崩潰(crash)和堆疊追蹤(stack trace)。代理則會交給你更多東西,包含一份報告(呼叫鏈、影響聲明、建議的嚴重程度)以及支持該報告的產物,例如你可以針對真實程式碼執行的概念驗證(proof-of-concept)。
所有這些都讓結果易於閱讀且易於信任,尤其是可執行的概念驗證。因此,不要計算代理產生了多少個候選項目。要計算有多少個被證明是真實的。
工作如何組織
我們針對一個目標平行執行許多代理。它們透過儲存庫本身進行協調,在版本控制中共享狀態,且沒有中央程序來分配工作。一個代理會在其他代理能看到的地方寫下聲明,執行工作,然後提交(commit)。
我們從 Anthropic 關於使用代理群建立 C 編譯器的文章中獲得了這種方法,該方法以相同的方式進行協調。沒有需要建立或維護的中央協調器,出錯的可能性也較小。
角色是由發現的工作所產生的:
- 偵察(Recon)將攻擊面轉化為具體、可測試的假設。不是「稽核解碼器」,而是「這個欄位在此點之後是受信任的;這是它應該保持的屬性、它可能被破壞的方式,以及能夠解決它的證明。」
- 狩獵(Hunting)採用一個假設,追蹤程式碼路徑,並嘗試建立一個重現程式(reproducer)。
- 填補空白(Gap-filling)檢視哪些被接受、哪些被拒絕,編寫下一批假設,並追蹤覆蓋率,以免代理不斷重複相同的領域。
- 驗證(Validation)獨立重新檢查每個候選項目,移除重複項,並做出決定。
我們並沒有發明這個流程。Cloudflare 描述了相同的階段:偵察、平行狩獵、獨立驗證、去重、報告,他們的文章幫助塑造了我們的流程。
以下是候選項目在被視為正式發現之前的樣貌:
目標: 攻擊者實際可以觸及的元件與進入點 不變量: 必須保持的屬性 機制: 可能導致其破壞的具體方式 成功: 可觀察的證明:恐慌、停滯、接受無效輸入 重現程式: 針對真實程式碼執行的獨立產物 去重: 一個鍵值,確保兩個代理不會追逐同一個目標
這個綱要(schema)的存在是有原因的。它強制要求一個具體、可測試的聲明以及明確的完成定義。必須寫下可觀察證明的代理,不能退而求其次地說「這看起來有風險」。
無法重現就等於沒發生
有一條規則比其他任何規則都重要。除非有一個獨立的產物能夠針對真實程式碼重現失敗,並且能讓非原作者的人執行,否則候選項目就不能算是正式發現。
重現程式不會閱讀報告,也不在乎模型聽起來有多自信。它要麼能執行,要麼不能。
它的大部分價值在於它所捕捉到的誤報(false positives)。其中有三種情況反覆出現,每一種都是代理因為錯誤的原因而過關:
- 僅在除錯版本(debug build)中發生的恐慌。以軟體實際發布的方式編譯並執行它,數值只會發生迴繞(wraps around)。沒有任何東西崩潰。它看起來像崩潰,但其實不是。
- 手動建立某些內部數值的重現程式,這些數值是任何真實輸入都無法產生的,因為攻擊者控制的每個路徑都會在更早的階段拒絕它。這個錯誤只會針對一個沒有任何可觸及路徑會以這種方式呼叫的函式進行「重現」。
- 在形式化驗證(formal-verification)工作中,一個通過了但並不代表你想要的意思的證明。無論程式碼做什麼,該陳述都是顯然成立的(trivially true),或者它比你想要捕捉的屬性更弱。驗證者滿足了條件,但該定理並沒有約束你真正關心的行為。
這些都不是新鮮事。這就像一個測試因為實際上沒有檢查任何東西而通過一樣。新鮮的是數量。代理編寫無用版本的速度與真實版本一樣快,而且同樣自信。因此,檢查必須是自動化的。你不能指望代理能自己發現錯誤。
訊噪比是大部分的工作
大多數候選項目都是錯誤的、重複的或超出範圍的。這不是方法的問題;這就是它的運作方式。目標是快速拒絕錯誤的項目,並用難以反駁的證明來支持真實的項目。
每個存活下來的候選項目都會接受兩次獨立檢查。真實的攻擊者在正常設定下真的能觸及它嗎?與成功後對網路造成的代價相比,攻擊者需要付出什麼代價?任何單一對等節點都能觸發的錯誤,與需要特殊存取權限或大量資源的錯誤截然不同。
所有內容都會與一份持續更新的清單進行比對,該清單包含已知、已修復或已拒絕的問題。如果沒有這個清單,代理會不斷重新發現相同的已關閉問題,並一再報告。
接受率因目標而異,而這種差異本身就很有用。針對成熟、經過嚴格稽核的程式碼執行此操作,幾乎沒有什麼能存活下來,但這仍然值得了解。「我們努力尋找但一無所獲」是一個真實的結果。針對較少探索的程式碼,或針對形式化驗證的程式碼(其中機器檢查的證明涵蓋了一個模型,而部署的位元組碼僅被假設與其相符)執行此操作,則會有更多項目通過。
我們不是唯一發現分類才是困難部分的人。Cloudflare 的主要心得是,狹窄的範圍勝過廣泛的掃描。Anthropic 的基於屬性測試的代理產生了大約一千份候選報告,然後使用排名和專家審查將其縮減到頂級層次,其準確率約為 86%。生成部分是簡單的。我不打算在這裡公布我們自己的數據;因為這些數據與特定目標綁定,它們更能說明目標的情況,而不是方法本身。
代理擅長什麼,以及它們在哪裡會產生誤導
兩個方向都有炒作,所以這裡有一份簡單的清單,列出代理做得好的地方以及它們會產生誤導的地方。
| 擅長 | 容易誤導 |
|---|---|
| 同時閱讀規格與程式碼 | 看似可觸及但實際無法觸及的呼叫鏈 |
| 陳述並檢查真實的不變量 | 操弄成功檢查(因為錯誤的原因而通過) |
| 從一行想法起草重現程式 | 誇大嚴重程度以匹配報告聽起來有多戲劇化 |
| 在你查看之前建議根本原因 | 跨越一系列有效步驟的錯誤 |
這種劃分在不同任務之間甚至不是穩定的。Stanislav Fort 在真實漏洞上測試了一系列模型,稱之為參差不齊的邊境(jagged frontier),或者說,一個在某個程式碼庫上能恢復完整漏洞利用鏈的模型,在另一個程式碼庫上可能會在基本的資料流追蹤上失敗。你不能假設一個好結果意味著下一個結果也能成立,這也是每個候選項目都要獨立檢查的另一個原因。
最後一列是重點。單一代理會話擅長單次推理(one-shot reasoning),但不擅長跨越一系列步驟的錯誤,在這些步驟中,每一步都是有效的,只有順序是錯誤的。對於這些情況,代理不是搜尋工具。它的工作是建議哪些序列值得透過有狀態的測試框架來執行。以這種方式使用,效果很好。如果用來取代測試框架,它會錯過最昂貴的錯誤,也就是那些只在一系列步驟中才會出現的錯誤。
保持誠實
幾個習慣就能完成大部分讓代理發現結果值得信賴的工作,而且這些習慣都不複雜。
- 每個產物的出處(Provenance):是什麼產生了它、在什麼脈絡下、針對哪個修訂版本。一個發現應該是你在幾個月後還能重新執行的東西。
- 在關鍵處保持確定性(Determinism):單一環境、單一建置與執行方式,因此「重現」在每台機器上都意味著同一件事,而不僅僅是在發現它的那台機器上。
- 規範而非腳本:告訴代理什麼是重要的、不變量以及真實發現的標準,而不是給予編號的程序。過度腳本化的代理會像過度指定的測試一樣崩潰,它們會在步驟不再合理時繼續遵循步驟。一項關於儲存庫脈絡檔案的研究也發現了同樣的事情:額外的要求降低了任務成功率,並使成本增加了 20% 以上,作者建議將脈絡保持在最低要求。
- 由人做出最終決定:代理只提供建議。它們不決定什麼是真實的、什麼是已知問題的重複項,或者什麼內容要在何時披露。
瓶頸轉移了
AI 並沒有取代安全研究人員。它轉移了工作。過去用於提出和追蹤假設的時間,現在用於大規模地判斷它們,包含建立預言機、執行分類、維護已知問題清單以及處理披露。
瓶頸並沒有消失。它從尋找錯誤轉移到了信任結果,這是一個更好的位置,因為這正是人類判斷力真正發揮作用的地方。但它仍然是一個瓶頸,忽略這一點會導致你最終發布一個錯誤的「一切正常」。
讓這項工作順利進行的實踐方法並不新鮮。可重現的失敗、真實的預言機以及仔細的分類,正是過去十五年來將模糊測試從研究主題轉變為標準實踐的相同方法。工具是新的。實踐方法則不是。
工具持續變化的速度有多快,這是一個懸而未決的問題。Nicholas Carlini 行事謹慎,且曾經也是個懷疑論者,他主張指數級增長的情況值得認真對待,即使他對此保留了很大的誤差範圍。如果生成端攀升得如此之快,判斷端也必須隨之攀升,否則產出的內容與實際驗證的內容之間的差距只會越來越大。
對於以太坊所依賴的系統來說,這才是重要的部分。代理讓我們能涵蓋比手動操作多得多的範圍。作為交換,它們要求我們在大量聽起來自信滿滿的聲明中,進行更仔細的判斷。這是一筆值得的交易,只要你記住,判斷才是真正的核心產品。


