---
title: 資安掃描工具說明 — claude-security plugin
brand: Guidant AI · **FR-075** jedi-* 套件安全掃描
eyebrow: FR-075 · 工具說明與踩坑紀錄 · 2026-09-06
h1: 我們用什麼工具在找資安問題，它怎麼運作
lede: 這份文件說明我們這兩天在用的資安掃描工具——**它做什麼、怎麼用、找到什麼、幫到什麼**，以及過程中撞到的問題與我們怎麼調整。**不需要技術背景也能讀完。**
chips: [{text: 已掃 5 個模組, kind: ok}, {text: 找到 17 個問題, kind: warn}, {text: 含 1 個最高等級, kind: crit}]
footer: 資料來源為實際掃描紀錄與 Notion 任務卡，非估算值。
---

## 一分鐘版 {#tldr nav="一分鐘版"}

我們請一個 AI 團隊，把自己產品的程式碼從頭到尾讀一遍，找出「攻擊者可以做到、但不該做到的事」。

::: statgrid
::: stat
[5]{.v}[已掃完的模組]{.k}
:::
::: stat
[266]{.v}[規劃覆蓋的程式檔]{.k}
:::
::: {.stat .warn}
[17]{.v}[已確認的資安問題]{.k}
:::
::: {.stat .crit}
[1]{.v}[最高等級（已排最優先）]{.k}
:::
:::

**最重要的一個發現**：有一支「忘記密碼」的功能，會把重設密碼用的通行憑證直接回傳給呼叫的人。**知道對方的 email，就能接管任何帳號，包含最高權限的管理員**——而且不需要收到那封信。這是自動掃描找出來的，人工review 多年沒發現。

---

## 這個工具是什麼 {#what nav="是什麼"}

它是 Claude Code 官方推出的一個外掛（plugin），名字叫 **claude-security**。

用日常一點的比喻：**它像是請一組資安顧問來看你的原始碼**，差別在於這組顧問是 AI，可以一次派十幾個人同時看、不用排時間、不用簽保密協定，而且**程式碼完全不離開你的電腦**。

::: {.callout .decided}
**它不是防毒軟體，也不是防火牆。**

防毒是「有壞東西進來時擋掉」，這個工具是「**在壞東西進來之前，先找出門有沒有鎖好**」。它在開發階段用，不是在被攻擊時用。
:::

### 它跟一般的掃描工具差在哪

市面上已經有很多自動掃描工具（我們也有在用，例如 SonarQube）。差別是這樣的：

::: grid2
::: {.card .warn}
#### 傳統掃描工具
靠**比對規則**：「看到這個寫法就報警」。

好處是快、便宜、穩定。
壞處是**只找得到規則裡有的東西**——「這個功能忘了檢查權限」這種問題，沒有固定寫法可以比對，規則抓不到。
:::
::: {.card .ok}
#### 這個 AI 工具
靠**讀懂邏輯**：追一筆資料從使用者送進來，一路經過哪些檢查，最後做了什麼事。

好處是找得到「規則抓不到」的邏輯漏洞。
壞處是慢、貴，而且會誤報——所以才需要下面說的驗證機制。
:::
:::

**兩者是互補，不是取代。** 這個工具的官方說明自己也這樣寫：它不取代既有的掃描、相依套件檢查與人工 code review。

---

## 它怎麼運作（機制） {#how nav="機制"}

這是這份文件最值得理解的部分。工具的可信度來自它的**內部制衡設計**，不是來自「AI 很聰明」。

整個流程分三段：

```{.mermaid cap="圖 1 — 掃描的三段式流程"}
%%{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 審查，而他們拿到的指令是去推翻它**：

::: {.callout .crit}
**驗證員的原始指令（翻譯）**

> 「給你一條候選發現和**一個任務：試著推翻它**。只有在你失敗的時候，這條發現才存活。」

> 「**誠實投票，不要去猜別人會怎麼投、也不要猜什麼才是『正確答案』。三個都投贊成的面板一文不值。**」
:::

而且三個驗證員**各看不同角度**，不是三個人重看一遍：

::: grid2
::: {.card}
#### 第一位：攻擊者到得了嗎？
這條路在正常安裝的情況下走得通嗎？資料真的是外人可以控制的嗎？是不是只有其中一條路沒鎖、其他都鎖了？
:::
::: {.card}
#### 第二位：到得了又怎樣？
真的會造成宣稱的後果嗎？那些資料真的敏感嗎？
:::
::: {.card}
#### 第三位：是不是已經有東西擋住了？
是不是框架預設就擋了？是不是上一層已經檢查過了？
:::
::: {.card .ok}
#### 三票 → 至少兩票同意才留下
這一輪的實際結果：**5 條候選，最後只留下 2 條**。被刪掉的一半就是這個機制的價值。
:::
:::

### ③ 票數由程式算，AI 碰不到

最後這步容易被忽略，但很重要：**票怎麼算、報告能不能蓋「已驗證」的章，是由一支固定的程式決定的，AI 沒有權限改。**

工具的作業手冊明文禁止 AI 自己寫票數檔案，理由寫得很直白——**不然「已驗證」這三個字就會變成 AI 自己說了算**。

::: {.callout .decided}
**所以看報告時可以這樣理解：**

「已驗證（verified）」= **這幾條經過了三方推翻測試而存活**，不是「這塊程式碼很乾淨」。

沒掃到的、被說服的，不在這個保證範圍內。
:::

---

## 這兩天實際找到什麼 {#found nav="找到什麼"}

我們把 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 個），皆已處理 |

### 值得單獨說明的兩個發現

::: {.callout .crit}
**最高等級｜忘記密碼會把「通行證」交給任何人**（S4）

正常的忘記密碼流程是：你按下按鈕 → 系統寄一封信給你 → 信裡有一組一次性通行證 → 你點進去改密碼。**通行證只有本人的信箱收得到，這是整個機制的安全前提。**

實際發生的是：這支功能**把那組通行證直接放在網路回應裡回傳給呼叫的人**。等於「只有本人收得到」這個前提被打破了。

**攻擊者只要知道對方的 email，兩步就能接管帳號，包含系統最高權限的管理員。** 全程不需要登入，也不需要碰到對方信箱。

已列為最優先修正（CM-1575）。現況：已修，1.21.0 出貨。
:::

::: {.callout .warn}
**中等級｜「停用」一個角色，其實沒有真的停用**（S5，昨天這一棒找到的）

管理員在畫面上把某個角色「停用」，直覺是那些人就不能用那些功能了。

實際上**只有選單消失，背後的功能呼叫照樣放行**。同樣的狀況也發生在已刪除的角色、已過期的授權上。

**這一條特別值得注意的地方**：同一份資料，在「產生側邊選單」的地方查得完全正確（有效期、租戶條件都有檢查），但在「決定能不能執行」的地方完全沒檢查。**同一件事，系統裡有兩套判斷標準，而且已經對不上了。**
:::

---

## 這對開發與產品的實際價值 {#value nav="價值"}

::: grid2
::: {.card .ok}
#### ① 找到人工看不到的問題
上面那條最高等級的漏洞，程式碼一直都在那裡，人工 review 沒發現。原因不難理解：**要同時看三個不同檔案、還要注意到「寄信用的那個值」跟「回傳的那個值」是同一個**，人在讀 code 時很難把這三處串起來。
:::
::: {.card .ok}
#### ② 出貨前先關門
產品即將以落地版交付給客戶。**軟體一旦裝到客戶機房，修一個洞的成本跟出貨前完全不是同一個量級**——要重新出版、通知、排維護時間。現在花的時間是買這個。
:::
::: {.card .ok}
#### ③ 留下可查的紀錄
每一輪都留下報告、版本戳記與票數紀錄。**客戶若問「你們有沒有做資安檢查」，這是拿得出來的東西**，而不是一句「我們有注意」。
:::
::: {.card .warn}
#### ④ 但它不是保證
掃過 ≠ 安全。它會漏、會被程式註解說服（下面有實例）。**它是「多一雙眼睛」，不是「通過認證」。**
:::
:::

---

## 這兩天撞到的問題，以及我們怎麼調整 {#issues nav="踩到的坑"}

這段是實話實說。工具很有價值，但不是開箱就順。

### 問題一：第一次設定太貴，跑到一半得喊停

第一輪用了中等強度（medium）。工具把套件切成很多小塊，**每塊都派一個 AI 去讀，結果同一個檔案被八個 AI 各讀了一遍**——因為它們彼此不共享看過的東西。

跑了 40 分鐘、派出 40 個 AI，收到 32 條候選，**因為成本明顯失控而在驗證階段開始前手動停掉**。那 32 條因此**從未經過驗證面板**，只能當參考不能當結論。

::: {.callout .decided}
**調整**：改用最低強度（low）——**只派 1 到 2 個研究員讀完整個範圍，驗證面板照樣三人不打折**。

從第一輪結果回頭看，medium 多出來的 30 幾個 AI，主要產出的是**重複發現，不是新發現**。
:::

### 問題二：連續四棒全軍覆沒，原因不是設定，是「記憶體不夠」

這是最花時間的一個坑，前後燒掉大半天。

四個模組（43、49、47、74 個檔）連續失敗：AI 讀到一半就被系統判定「卡住」而砍掉，然後從零重來，**永遠讀不完**。

原因追出來是這樣的：

::: {.callout .crit}
**AI 一次能記住的內容有上限。** 我們原本用的模型上限較小，而工具要求研究員「讀完每個檔、追完每個呼叫、不信任何註解」——讀到二十幾萬字時，它每一步思考都變慢。

而工具有一條規則：**超過 180 秒沒有任何動作就判定卡死、直接砍掉重來**。

於是形成死循環：讀得越多 → 想得越慢 → 被砍 → 重新開始 → 又讀到同一個地方被砍。

**一個被砍掉的 AI 的實際紀錄：跑了 411 個回合、產出 91 萬字、讀了 30 個檔、下了 200 多次搜尋指令，然後死掉，什麼都沒交出來。**
:::

::: {.callout .decided}
**調整：只改一件事——把主控端換成記憶容量大 5 倍的模型**（Opus 5 1M）。

掃描範圍、強度、卡片內容**全部不動**。因為底下的 AI 會繼承主控端的模型，換一個地方等於全部換掉。

**結果**：昨天這一棒（49 個檔）**一次跑完、零中斷、零重試**，14 個 AI 全數交卷。

代價是成本約為原本的三到五倍。但原本的成本是「**跑三小時然後什麼都沒有**」，所以這個交換很划算。
:::

### 問題三：AI 會「越界」——跑去讀別人的範圍，然後回報別人已經找過的東西

有一棒交出 9 條發現，**其中 8 條是前面某一棒早就找到、而且已經開單在修的**。

原因是研究員為了追清楚脈絡，會主動往範圍外讀——**這其實是它被要求的行為**（追到每個呼叫方為止），不能算它做錯。

::: {.callout .warn}
**這裡有一個容易誤解的點**：驗證面板只檢查「**這條發現成立嗎**」，**不檢查「這條發現在不在你指派的範圍內**」。

所以重複的東西驗證起來一樣會通過三票，**看起來就像新發現**。這只能靠人工比對抓出來。
:::

::: {.callout .decided}
**調整**：
1. 派工單上**明寫「不要讀這些已經掃過的路徑」**
2. 收到報告後，**人工逐條比對是否重複**，重複的標記為「越界」不列入該棒成果
3. **不縮小掃描範圍**——已經證實研究員為了追脈絡一定會往外讀，切小只會多跑一輪重複的東西
:::

### 問題四：工具會被程式碼裡的註解說服

有一段程式碼的說明文字寫著「這是刻意這樣設計的」，研究員讀到就接受了，沒有繼續追。**但那一段實際上是有問題的**，是後來人工複查才補開單的。

這件事有點諷刺——工具的指令明明白白寫著「不要相信註解」，但**當註解寫得夠有說服力時，它還是會被說服**。

::: {.callout .decided}
**調整**：**高等級以上的每一條，由人親自打開檔案核對過**，核對結果（屬實／誇大／誤判，以及理由）寫進報告。**不照抄工具輸出。**

昨天那一棒的兩條發現，都是這樣逐層追過才寫進報告的——包含去確認一個關鍵前提：「使用者名單真的會出現在回應裡嗎？」如果答案是否，那條發現的嚴重度就要往下調。
:::

---

## 想自己用的話 {#howto nav="怎麼用"}

::: grid2
::: {.card}
#### 啟動
在 Claude Code 裡輸入 `/claude-security`，選「Scan codebase」，照著選單走即可。
:::
::: {.card}
#### 建議設定
**強度選 low**、範圍**一次一個模組（40 個檔上下）**、主控端**用大容量模型**。
:::
::: {.card .warn}
#### 要有心跳準備
一個模組大約**跑 2 到 3 小時**，而且**中途不能做別的事**。它是全有全無——中斷就整輪報廢。
:::
::: {.card .warn}
#### 收到報告不要照單全收
**高等級的自己開檔核對**，並確認有沒有越界重複。工具給的嚴重度會偏高。
:::
:::

::: {.callout .decided}
**一句話總結**

這個工具**值得用，但要有人看著**。它負責把「可能有問題的地方」從幾萬行程式碼裡撈出來，**判斷哪些是真的、多嚴重、該不該修，仍然是人的工作。**
:::
