跳到主要內容
45% 的 AI 程式碼帶漏洞:五個該打開 diff 就看的地方

45% 的 AI 程式碼帶漏洞:五個該打開 diff 就看的地方

AI 生成的程式碼看起來很乾淨,問題不在語法在架構。Veracode 測 100 多個模型的結論是 45% 帶 OWASP Top 10 漏洞,兩年沒改善。這篇給五個可執行的審查點:資料存取、錯誤處理、狀態放哪、權限邊界、單位成本,以及怎麼把它們變成 agent 看得懂的約束。

目錄+

你打開 agent 送上來的 diff,掃了一遍。

命名整齊、註解完整、格式像照著風格指南寫的。沒什麼好挑的,approve。

問題就出在這裡。

Veracode 在今年春季的 GenAI Code Security Update 測了一百多個大型語言模型、八十個編碼任務。45% 的產出帶有 OWASP Top 10 漏洞。

真正難看的是後半句:這個數字兩年沒有改善,儘管期間每一代模型發布時都宣稱自己更好了。Java 超過七成,XSS 有 86% 沒擋住。

這篇拆五個你該打開 diff 就看的地方,以及怎麼把它們變成 agent 自己看得懂的約束。


為什麼 AI 寫的爛程式碼特別難抓

先講一個機制上的差異,這決定了你該用什麼方式審。

人類寫的爛程式碼,看起來就爛。命名怪、結構亂、風格不一致。你在 review 的時候會警覺,因為它看起來不對。

AI 寫的爛程式碼不給你這個訊號。

它語法乾淨、註解完整、格式漂亮。乾淨的語法跟健全的架構是兩回事,但只有前者看得見。

這件事的規模有多大?New Relic 的《State of AI Coding 2026》調查裡,78% 的組織說生產事故明顯上升,86% 說資深工程師救火的次數變多,82% 在過去半年至少發生一次由 AI 程式碼造成的重大故障,74% 說至少四分之一的 AI 程式碼上線後需要大改。

同一份調查裡還有一個數字解釋了為什麼會這樣:62% 的工程主管承認,團隊經常或總是信任 AI 產出到不逐行檢查就上線。

而 AI 生成的程式碼引入的嚴重執行期問題,大約是人類基準線的 1.7 倍。


基本功真正的用途,是看出有哪些取捨存在

系列第一篇提過吳恩達對「軟體工程基本功」的定義,跟大多數人想的不一樣。

他說工程本來就是在成本、擴展性、可靠度、速度之間做取捨,加上安全和隱私之後更複雜。而基本功的價值,是讓你先意識到有哪些取捨存在。

跳過這段的人會遇到兩個問題:不知道該餵 agent 什麼上下文,也看不出 agent 正在做糟糕的架構決定。

所以審查的方法不是逐行讀。是對每一個架構決定問同一句話:

這個決定犧牲了成本、擴展性、可靠度、安全性裡的哪一個?

答得出來,就是有意識的取捨。答不出來,就是你的缺口。

下面五個,是最常見的答不出來的地方。


1. 資料存取模式,犧牲的是擴展性

它會怎麼寫: 在迴圈裡逐筆查詢、SELECT * 全欄位撈、沒有索引就直接 filter。

為什麼: 在你給它看的那個檔案裡,這樣寫最短、最好讀,而且測試資料只有五筆的時候跑得飛快。

你該問: 這段程式碼在資料量一萬筆的時候會發幾次查詢?

N+1 在 code review 裡很難用眼睛抓,因為迴圈跟查詢常常隔了兩層抽象。比較可靠的做法是在測試環境打開查詢紀錄,跑一次真實流程數 SQL 數量。


2. 錯誤處理,犧牲的是可觀測性

它會怎麼寫: 整段包一個 try/catch,catch 裡回傳一個安全的預設值。

為什麼: 這樣測試會過,而且看起來很「穩健」。

你該問: 這個錯誤被吞掉之後,我要從哪裡知道它發生過?

這是五個裡面最惡性的一種,因為症狀是沒有症狀。系統不會崩,它只是安靜地回傳空陣列,然後三週後有人問為什麼報表數字對不起來。

判準:每一個 catch 都要嘛往上拋、要嘛留下一筆帶脈絡的紀錄。兩者都沒有的 catch,就是在藏證據。


3. 狀態放在哪,會在 serverless 上直接爆

它會怎麼寫: 模組層級的變數當快取、記憶體裡的 Map 存 session、全域計數器做 rate limit。

為什麼: 在單一長駐 process 的心智模型裡,這些做法完全正確。它不知道你部署在哪。

你該問: 這個 process 隨時會被回收的話,這段還對嗎?

Vercel Functions 這類環境要當成無狀態而且短命的:沒有持久的記憶體、沒有持久的檔案系統、不能跑背景常駐程式。要保存狀態就得往外放,用 Blob 或 marketplace 的 Redis、Postgres。

這一條特別值得盯,因為它在本機開發時永遠是對的。


4. 權限邊界,犧牲的是安全

它會怎麼寫: 拿有最高權限的那把金鑰到處用,因為那把一定不會權限不足。

為什麼: 權限錯誤是它最難自己 debug 的一類問題,用最大權限可以一次繞過。

你該問: 這段程式碼如果被使用者的輸入影響,最壞能做到什麼?

這一條的數字最刺眼。GitGuardian 的《State of Secrets Sprawl 2026》統計,去年公開 GitHub commit 新增了兩千八百六十五萬筆寫死的機密,年增 34%,是有紀錄以來最大的單年跳升。而 AI 協作的 commit 洩漏機密的比率是 3.2%,全體基準線是 1.5%,大約兩倍。

同一份報告在公開 GitHub 的 MCP 設定檔裡找到 24,008 筆機密,其中 2,117 筆確認仍然有效。

Apiiro 對一家 Fortune 50 公司的研究則顯示,AI 工具產生的資安發現量是人類基準的十倍,其中權限提升路徑增加 322%。


5. 每次請求的成本,犧牲的是單位經濟

它會怎麼寫: 每一次請求都打一次 LLM,不快取、不批次、不分級。

為什麼: 你要求的功能它做到了。成本不在需求裡,就不在它的考慮裡。

你該問: 這個功能一天被呼叫一萬次的話,帳單是多少?

這一條對獨立開發者和小團隊特別致命,因為它不會讓任何測試失敗。功能是好的,直到月底。

止血的三個點:能用快取的先快取、能用小模型的不要用大的、能在程式碼裡判斷的不要問模型。全部丟 Cloudflare 那篇算過最壞情況的帳單長什麼樣,值得在架構定案前先看一次數字。


把檢查點變成 agent 看得懂的約束

上面五條你自己記得沒有用。你會忘,而且你不在的時候 agent 照樣寫。

口頭叮嚀會被 context 擠掉,程式碼層級的約束不會。

三個層次,由弱到強。最弱的是 rules 檔:把「這個專案的狀態一律走 Redis,不要用模組變數」寫進 agent 的規則檔,成本最低,但仍然可能被長對話稀釋。中間是型別:讓錯誤的做法在型別層級就編譯不過,例如把 service role client 包成一個只能在特定模組匯入的型別。最強的是 CI 檢查:查詢數量上限、禁用 API 的 lint 規則、機密掃描。這一層 agent 繞不過去。

AI Coding 時代的工程師工具鏈那篇講的就是這件事:型別系統和規則檔為什麼比選哪個模型更關鍵。

而這三層剛好也是上一篇談的六個判斷點裡「什麼時候該加驗證器」的具體答案。驗證器不一定是測試,一條 lint 規則也算。

利益揭露:以下是聯盟連結。要在本機重現 serverless 的行為,或者跑本地模型做程式碼審查,記憶體比核心數重要,麗臺 RTX PRO 4000 Blackwell 的 24GB 規格上剛好夠跑 Llama 3 70B 的量化版。


常見問題

AI 生成的程式碼有多不安全?

Veracode 今年春季的 GenAI Code Security Update 測了一百多個模型、八十個編碼任務,45% 的產出帶有 OWASP Top 10 漏洞,而且兩年沒有改善。Java 超過七成,XSS 有 86% 沒擋住。

為什麼 AI 寫的程式碼在 code review 比較難抓?

因為它語法乾淨、註解完整、格式符合風格指南,缺的是架構一致性。人類寫的爛程式碼看起來就爛,你會警覺;AI 寫的爛程式碼看起來很好,你會直接放行。

AI 幫我做的架構決定,我該問哪些問題?

每個決定都問它犧牲了成本、擴展性、可靠度、安全性裡的哪一個。答不出來的地方就是你的缺口。

怎麼讓 agent 自己避開這些問題?

把檢查點寫成型別、rules 檔、CI 檢查。口頭叮嚀會被 context 擠掉,程式碼層級的約束不會。


這五條有一個共通點:agent 沒有一次是「寫錯」的。

它每一次都在你給的條件下選了最合理的做法。問題出在你沒說的那些條件,而它不會問。

所以問題不是「AI 寫的程式碼能不能信」。

是你上一次打開 diff 的時候,看的是它寫了什麼,還是它替你決定了什麼?