你是不是也有過這種感覺?
寫了一堆功能,覺得差不多了,於是請工程師或用 AI 跑一次資安掃描器(Scanner)。
然後螢幕上湧出幾百行報告:「缺少 Security Header」、「依賴庫有已知漏洞」、「密碼硬編碼」。你看得眼花撩亂,不知從何改起。最後為了趕上線,把那些聽起來很嚴重的修掉,那些聽起來像噪音的就暫緩。
結果上線後,一個不起眼的路由被繞過,整個資料庫被清空。
問題出在哪?不是掃描器不夠強,而是你跳過了最關鍵的一步:先寫憲法,再跑掃描器。
這個觀念來自我開源的專案 threat-model-skill(GitHub:https://github.com/fishbob889/threat-model-skill )。它是一套給 Claude Code 用的指令集,專幫不會資安的開發者做威脅建模。它的核心邏輯只有一個:在跑工具之前,先用自然語言定義出「絕對不能被打破的規則」。
這篇文章會帶你走一遍這個過程。不講艱澀理論,只談怎麼用白話文保護你的系統。
一、資安底層:守護 CIA 三要素
在做任何檢查前,我們要先問自己:「我們到底怕什麼?」
業界有一套最基礎的分類法,叫 CIA 三要素。每一種資安事件,最後都能歸類到這三者之一:
-
機密性(Confidentiality):資料只讓該看的人看到。
– 例子:資料庫裡的密碼、API 金鑰、客戶個資。
– 失敗場景:你把金鑰寫在前端 JavaScript 裡,任何人按 F12 開開發者工具就能看到。 -
完整性(Integrity):資料和系統只能被授權的人、用授權的方式改動。
– 例子:訂單金額、使用者角色、帳單。
– 失敗場景:一個普通登入帳號,呼叫管理員 API 把自己升級成 admin,或是刪掉別人的資料。 -
可用性(Availability):該提供服務的時候要能提供。
– 例子:網站能正常開啟、API 有回應、備份還原得回來。
– 失敗場景:一個沒有限速的登入端點,被機器人攻擊幾萬次,導致網站癱瘓。
為什麼要先講 CIA?因為同樣的漏洞,破壞不同元素的代價完全不同。
掃描報告裡最常見的錯誤,就是把「DoS(影響可用性)」和「授權繞過(影響完整性/機密性)」混在一起排。結果,真正要命的漏洞被幾十條「缺個 Security Header」的小問題淹沒了,你以為沒事了,上線就被駭。
所以,做資安檢查的第一步,不是拿工具掃,而是確認每個漏洞「破壞的是 C、I 還是 A」。
二、五個核心問題:先寫憲法,再跑掃描器
這套方法來自 OpenAI 的 Codex Security plugin,我把它轉化為 Claude 可以執行的流程。順序很重要:先問清楚,再開掃。
問題 1:哪些東西被偷或被改會出大事?(重要資產)
把資產列成表:金鑰、密碼、含個資的資料表、簽章用的 secret,以及「對其他機器下命令的能力」本身。
從程式碼推:設定檔有哪些欄位?哪個 model 有加密欄位?哪個 table 有客戶資料?每一項寫下:放在哪、誰能讀、外洩或被改的後果。
問題 2:誰能碰哪些資料?(角色權限)
畫一張矩陣:匿名 / 一般使用者 / 管理員 / 機器帳號,各自可讀、可寫、可執行什麼。
重點是:不要看 README,要看程式碼裡每一條 API 路由實際掛的是哪個認證檢查。
這是我實戰中最常抓到的坑。人工盤點清單往往是「說法」(例如:README 說這是 admin-only),但測試才是「證據」。第一次用這套方法時,我們就發現一條漏洞:盤點說是 admin-only,但測試證明任何登入帳號都打得到那條路徑。
問題 3:哪一段是你管不到的?(信任邊界)
你控制不了的地方,就是黑客進來的地方。
這些地方包括:使用者輸入、第三方 API 回傳的東西、你 SSH 過去的其他機器回傳的輸出、瀏覽器。還有一個 2026 年新增的重點:AI agent 讀進來的任何內容(網頁、PR、貼上的文字、掃描報告)。Agent 讀到的文字可能含有指令,這是一種新的攻擊來源。每一條邊界要寫下:什麼東西穿過去、誰控制它、現在有什麼防線。
問題 4:哪些規則絕對不能被打破?(安全不變條件 Invariants)
這是整套方法的核心,也是 skill 名字裡「憲法」的意思。
句型固定為:「⟨對手⟩具備⟨能力⟩時,不能⟨結果⟩」。
範例:
– 「匿名請求不能讀到任何需登入的資料。」
– 「非管理員不能改變任何機器的狀態。」
– 「JWT 只接受 header,不接受 query string。」
– 「掃描目標只能是白名單內的主機。」
這裡有兩個規矩:
1. 只寫程式碼真的保證的。還沒保證的放到「已知弱點」那一節,不要假裝有。
2. 每一條要標「落實等級」:L1 只寫在文件裡、L3 有一支沒它就會 fail 的測試、L5 有 runtime 檢查或 hook 自動攔。還要寫「怎麼驗」——寫不出驗證方法的 invariant 是願望不是保證。
有了這份清單,掃描器的每一條輸出都要回答「它違反哪一條 invariant」。對不到的,不是這裡的 finding,登記後轉給負責的流程(依賴升級、反代設 header、限流),報告就不會被噪音淹掉。
問題 5:外面有哪些門是開著的?(攻擊入口)
列出所有入口:沒有認證的路由(登入頁本來就沒有)、監聽的 port、SSH、webhook、定時抓外部資料的排程。
最容易被忽略的一項:平台預設值。
2026 年大部分 vibe coding(快速原型開發)出事的案例都不是程式碼寫錯,是預設值:專案預設公開、資料庫 row-level security 預設關、CORS 預設 *、debug 模式沒關。
三、五問之後:掃描、判讀、修補
當我們寫完「憲法」,就可以開始跑 skill 了。它分為三個階段:
-
兩層掃描:
– 先跑決定性工具:gitleaks 找機密、pip-audit / npm audit 找依賴漏洞、bandit 找程式碼壞味道。每個工具不是「跑了」就是明講「跳過」,不能讓「沒跑」看起來像「沒問題」。
– 然後由 invariant 驅動語意層:對每一條 invariant 問「給我一個會違反它的請求」。 -
判讀:
每條 finding 拆成 Source(不可信輸入從哪進來)→ Control(路徑上該擋它的檢查,狀態是缺、被繞、範圍錯還是不完整)→ Sink(最後打到哪:執行命令、查資料庫、寫檔、另一台機器、機密)。路徑上有有效的 Control 就是誤報;沒有 Control 而且 Sink 打到資產,才是真的。嚴重度用固定的表算(影響 × 可達性),不靠感覺。 -
修補:
修在邊界(該有 Control 的地方),不是在 Sink 貼補丁;寫一支「修前會 fail、修後會 pass」的回歸測試,而且兩邊都真的跑一次;修完把 invariant 的等級往上升。
四、第一次實戰的結果
讓我們來看看實際效果。受試者是一套內部維運儀表板(FastAPI + Vue),透過 SSH 管理約四十台 Linux 機器,14 個 router、131 條路由。
只用了一個下午:
– 寫出 11 條 invariant。
– 9 條 finding 全部關閉,其中兩條是之前人工稽核漏掉的真實授權漏洞(任何登入帳號可對任一台機器封鎖或解封 IP;任何登入帳號可刪光整個文件庫)。
– 5 條 invariant 從「只寫在文件」升到「有測試」或「runtime 攔截」。
– 依賴漏洞 Python 47 條降到 4 條無修復版、npm 5 條清零。
同一套方法回頭用在專案自己的防護 hook 上,又找到四個繞過。
五、怎麼用?
如果你也想試試看這套方法,可以安裝我的 threat-model-skill。
安裝步驟:
git clone https://github.com/fishbob889/threat-model-skill ~/.claude/skills/threat-model
使用方式:
在 Claude Code 裡,對著你的專案說:「這個專案上線前做一次威脅模型」。
Claude 會先從程式碼推出憲法草稿,停下來給你看,你改完它才開始掃。產出兩份檔案放在專案的 docs/security/:
1. THREAT_MODEL.md(憲法):你的安全規則清單。
2. findings.md(finding 帳本):掃描結果與修補建議。
總結來說:
資安不是跑個工具就結束的任務,而是一個定義邊界、驗證規則的過程。先寫憲法,再跑掃描器,能讓你的報告從噪音變為行動指南。
喜歡這篇文章的話,歡迎分享給身邊寫程式的朋友。