FR-075 · 工具說明與踩坑紀錄 · 2026-09-06
這份文件說明我們這兩天在用的資安掃描工具——它做什麼、怎麼用、找到什麼、幫到什麼,以及過程中撞到的問題與我們怎麼調整。不需要技術背景也能讀完。
我們請一個 AI 團隊,把自己產品的程式碼從頭到尾讀一遍,找出「攻擊者可以做到、但不該做到的事」。
5已掃完的模組
266規劃覆蓋的程式檔
17已確認的資安問題
1最高等級(已排最優先)
最重要的一個發現:有一支「忘記密碼」的功能,會把重設密碼用的通行憑證直接回傳給呼叫的人。知道對方的 email,就能接管任何帳號,包含最高權限的管理員——而且不需要收到那封信。這是自動掃描找出來的,人工review 多年沒發現。
它是 Claude Code 官方推出的一個外掛(plugin),名字叫 claude-security。
用日常一點的比喻:它像是請一組資安顧問來看你的原始碼,差別在於這組顧問是 AI,可以一次派十幾個人同時看、不用排時間、不用簽保密協定,而且程式碼完全不離開你的電腦。
它不是防毒軟體,也不是防火牆。
防毒是「有壞東西進來時擋掉」,這個工具是「在壞東西進來之前,先找出門有沒有鎖好」。它在開發階段用,不是在被攻擊時用。
市面上已經有很多自動掃描工具(我們也有在用,例如 SonarQube)。差別是這樣的:
靠比對規則:「看到這個寫法就報警」。
好處是快、便宜、穩定。 壞處是只找得到規則裡有的東西——「這個功能忘了檢查權限」這種問題,沒有固定寫法可以比對,規則抓不到。
靠讀懂邏輯:追一筆資料從使用者送進來,一路經過哪些檢查,最後做了什麼事。
好處是找得到「規則抓不到」的邏輯漏洞。 壞處是慢、貴,而且會誤報——所以才需要下面說的驗證機制。
兩者是互補,不是取代。 這個工具的官方說明自己也這樣寫:它不取代既有的掃描、相依套件檢查與人工 code review。
這是這份文件最值得理解的部分。工具的可信度來自它的內部制衡設計,不是來自「AI 很聰明」。
整個流程分三段:
%%{init: {"theme":"base","themeVariables":{"primaryColor":"#eef2ff","primaryTextColor":"#1e293b","primaryBorderColor":"#6366f1","lineColor":"#64748b","secondaryColor":"#fef3c7","tertiaryColor":"#dcfce7","fontFamily":"system-ui, -apple-system, sans-serif","fontSize":"14px"}}}%%
flowchart TB
A["① 研究員<br/>讀程式碼、找可疑處<br/>(會多報)"] --> B["② 驗證面板<br/>三人各從不同角度<br/>試圖推翻(會刪掉)"]
B --> C["③ 程式統計票數<br/>AI 碰不到這一步"]
C --> D["產出報告<br/>蓋上驗證章"]
工具派出若干個「研究員」AI,每個拿到一批程式檔。它們的任務指令寫得很明確——我把原文翻出來:
「讀完給你的每個檔案。然後追著資料跑。 對每個可疑的地方,往回走到這筆資料是從哪裡進來的,中間經過的每一站都要讀,包含在別的檔案裡的。」
「不要相信註解。『上游已驗證過』『內部使用』『呼叫方已清理』這些都是寫程式的人的宣稱,他可能當初就想錯了,或者呼叫方後來被改過。要在程式碼裡自己確認,不然就不要當作依據。」
研究員只能讀,不能改、不能執行、不能連網。這是硬性限制,不是承諾。
這是整套設計最關鍵的地方。每一條被找到的問題,都要送三個「驗證員」AI 審查,而他們拿到的指令是去推翻它:
驗證員的原始指令(翻譯)
「給你一條候選發現和一個任務:試著推翻它。只有在你失敗的時候,這條發現才存活。」
「誠實投票,不要去猜別人會怎麼投、也不要猜什麼才是『正確答案』。三個都投贊成的面板一文不值。」
而且三個驗證員各看不同角度,不是三個人重看一遍:
這條路在正常安裝的情況下走得通嗎?資料真的是外人可以控制的嗎?是不是只有其中一條路沒鎖、其他都鎖了?
真的會造成宣稱的後果嗎?那些資料真的敏感嗎?
是不是框架預設就擋了?是不是上一層已經檢查過了?
這一輪的實際結果:5 條候選,最後只留下 2 條。被刪掉的一半就是這個機制的價值。
最後這步容易被忽略,但很重要:票怎麼算、報告能不能蓋「已驗證」的章,是由一支固定的程式決定的,AI 沒有權限改。
工具的作業手冊明文禁止 AI 自己寫票數檔案,理由寫得很直白——不然「已驗證」這三個字就會變成 AI 自己說了算。
所以看報告時可以這樣理解:
「已驗證(verified)」= 這幾條經過了三方推翻測試而存活,不是「這塊程式碼很乾淨」。
沒掃到的、被說服的,不在這個保證範圍內。
我們把 jedi-iam(負責登入與權限的核心套件)切成七段來掃,目前完成五段。
| 段次 | 掃什麼 | 檔數 | 結果 |
|---|---|---|---|
| S1 | 登入與外部帳號綁定 | 11 | 8 個問題(5 高、3 中) |
| S2 | 權限守門與提權路徑 | 8 | 0 個問題 |
| S3 | 雙重驗證與人機驗證 | 34 | 2 個問題(1 高、1 中) |
| S4 | 使用者資料與改密碼 | 43 | 5 個問題(2 最高、1 高、2 中) |
| S5 | 角色與權限能力 | 49 | 2 個問題(皆中) |
| S6 | 租戶與組織單位 | 47 | 1 個問題(中);原寫「待重跑」,現況:已重跑完成並修完 |
| S7 | 登入狀態與共用工具 | 74 | 首輪越界作廢;現況:已收窄為 29 檔重跑完成(1 個中等+人工 2 個),皆已處理 |
最高等級|忘記密碼會把「通行證」交給任何人(S4)
正常的忘記密碼流程是:你按下按鈕 → 系統寄一封信給你 → 信裡有一組一次性通行證 → 你點進去改密碼。通行證只有本人的信箱收得到,這是整個機制的安全前提。
實際發生的是:這支功能把那組通行證直接放在網路回應裡回傳給呼叫的人。等於「只有本人收得到」這個前提被打破了。
攻擊者只要知道對方的 email,兩步就能接管帳號,包含系統最高權限的管理員。 全程不需要登入,也不需要碰到對方信箱。
已列為最優先修正(CM-1575)。現況:已修,1.21.0 出貨。
中等級|「停用」一個角色,其實沒有真的停用(S5,昨天這一棒找到的)
管理員在畫面上把某個角色「停用」,直覺是那些人就不能用那些功能了。
實際上只有選單消失,背後的功能呼叫照樣放行。同樣的狀況也發生在已刪除的角色、已過期的授權上。
這一條特別值得注意的地方:同一份資料,在「產生側邊選單」的地方查得完全正確(有效期、租戶條件都有檢查),但在「決定能不能執行」的地方完全沒檢查。同一件事,系統裡有兩套判斷標準,而且已經對不上了。
上面那條最高等級的漏洞,程式碼一直都在那裡,人工 review 沒發現。原因不難理解:要同時看三個不同檔案、還要注意到「寄信用的那個值」跟「回傳的那個值」是同一個,人在讀 code 時很難把這三處串起來。
產品即將以落地版交付給客戶。軟體一旦裝到客戶機房,修一個洞的成本跟出貨前完全不是同一個量級——要重新出版、通知、排維護時間。現在花的時間是買這個。
每一輪都留下報告、版本戳記與票數紀錄。客戶若問「你們有沒有做資安檢查」,這是拿得出來的東西,而不是一句「我們有注意」。
掃過 ≠ 安全。它會漏、會被程式註解說服(下面有實例)。它是「多一雙眼睛」,不是「通過認證」。
這段是實話實說。工具很有價值,但不是開箱就順。
第一輪用了中等強度(medium)。工具把套件切成很多小塊,每塊都派一個 AI 去讀,結果同一個檔案被八個 AI 各讀了一遍——因為它們彼此不共享看過的東西。
跑了 40 分鐘、派出 40 個 AI,收到 32 條候選,因為成本明顯失控而在驗證階段開始前手動停掉。那 32 條因此從未經過驗證面板,只能當參考不能當結論。
調整:改用最低強度(low)——只派 1 到 2 個研究員讀完整個範圍,驗證面板照樣三人不打折。
從第一輪結果回頭看,medium 多出來的 30 幾個 AI,主要產出的是重複發現,不是新發現。
這是最花時間的一個坑,前後燒掉大半天。
四個模組(43、49、47、74 個檔)連續失敗:AI 讀到一半就被系統判定「卡住」而砍掉,然後從零重來,永遠讀不完。
原因追出來是這樣的:
AI 一次能記住的內容有上限。 我們原本用的模型上限較小,而工具要求研究員「讀完每個檔、追完每個呼叫、不信任何註解」——讀到二十幾萬字時,它每一步思考都變慢。
而工具有一條規則:超過 180 秒沒有任何動作就判定卡死、直接砍掉重來。
於是形成死循環:讀得越多 → 想得越慢 → 被砍 → 重新開始 → 又讀到同一個地方被砍。
一個被砍掉的 AI 的實際紀錄:跑了 411 個回合、產出 91 萬字、讀了 30 個檔、下了 200 多次搜尋指令,然後死掉,什麼都沒交出來。
調整:只改一件事——把主控端換成記憶容量大 5 倍的模型(Opus 5 1M)。
掃描範圍、強度、卡片內容全部不動。因為底下的 AI 會繼承主控端的模型,換一個地方等於全部換掉。
結果:昨天這一棒(49 個檔)一次跑完、零中斷、零重試,14 個 AI 全數交卷。
代價是成本約為原本的三到五倍。但原本的成本是「跑三小時然後什麼都沒有」,所以這個交換很划算。
有一棒交出 9 條發現,其中 8 條是前面某一棒早就找到、而且已經開單在修的。
原因是研究員為了追清楚脈絡,會主動往範圍外讀——這其實是它被要求的行為(追到每個呼叫方為止),不能算它做錯。
這裡有一個容易誤解的點:驗證面板只檢查「這條發現成立嗎」,不檢查「這條發現在不在你指派的範圍內」。
所以重複的東西驗證起來一樣會通過三票,看起來就像新發現。這只能靠人工比對抓出來。
調整:
有一段程式碼的說明文字寫著「這是刻意這樣設計的」,研究員讀到就接受了,沒有繼續追。但那一段實際上是有問題的,是後來人工複查才補開單的。
這件事有點諷刺——工具的指令明明白白寫著「不要相信註解」,但當註解寫得夠有說服力時,它還是會被說服。
調整:高等級以上的每一條,由人親自打開檔案核對過,核對結果(屬實/誇大/誤判,以及理由)寫進報告。不照抄工具輸出。
昨天那一棒的兩條發現,都是這樣逐層追過才寫進報告的——包含去確認一個關鍵前提:「使用者名單真的會出現在回應裡嗎?」如果答案是否,那條發現的嚴重度就要往下調。
在 Claude Code 裡輸入 /claude-security,選「Scan codebase」,照著選單走即可。
強度選 low、範圍一次一個模組(40 個檔上下)、主控端用大容量模型。
一個模組大約跑 2 到 3 小時,而且中途不能做別的事。它是全有全無——中斷就整輪報廢。
高等級的自己開檔核對,並確認有沒有越界重複。工具給的嚴重度會偏高。
一句話總結
這個工具值得用,但要有人看著。它負責把「可能有問題的地方」從幾萬行程式碼裡撈出來,判斷哪些是真的、多嚴重、該不該修,仍然是人的工作。