---
title: 遠端代理程式
eyebrow: Guidant AI 資安檢視 · 模組報告
h1: 遠端代理程式（jedi-remote-agent）
lede: 裝在客戶機房、代替我們去執行檢測工作的程式。**全案唯一一件「最嚴重」等級的問題在這裡**——而且它是整份報告中唯一一件不需要任何帳號就能得手的。
---

## 這塊在產品裡做什麼

客戶要做資安檢測，得有東西去**實際連上他們自己機房裡的主機**——跑掃描工具、抓設定檔、取回檢測結果。但那些主機在客戶內網，我們的雲端碰不到。

所以我們發一支**代理程式**給客戶，裝在他們機房裡。它像一個派駐在客戶端的員工：

::: grid2
::: {.card .plain}
#### 它平常在做什麼
1. 每隔一段時間**跟雲端報到**（「我還活著，有工作給我嗎」）
2. 雲端派工作下來，它**在客戶內網執行**
3. 做完**把結果回傳**
:::
::: {.card .warn}
#### 為什麼它是敏感目標
為了做事，它手上握有**客戶主機的帳號密碼**——遠端登入用的、Windows 管理用的、掃描工具的權杖。

**這點是理解後面問題的關鍵。**
:::
:::

---

## 檢視軌跡

**檢視期間**：2026-09-07 ～ 2026-09-17｜**範圍**：99 個檔案（模組本體 72、接線 16、借用的檢測模組 11）｜**共 5 輪**

> **原始技術報告**放在需求中心的 [FR-077 站](https://guidantai-feature-doc.jedicotech.com/FR-077-2609-remote-agent-security-scan/)，檔名見下表最後一欄。那裡有每一輪的完整技術細節、檔案清單與逐條推理，供需要深究或稽核抽查時查閱。

| 輪次 | 查什麼 | 檔數 | 覆核投票 | 結果 | 原始報告檔名 |
|---|---|---:|---|---|---|
| **R1** | 代理程式的身分與註冊——它怎麼證明「我是誰」 | 42 | 覆核未完整跑成（見下方說明） | 通過 7 條，**開出 4 張修正工單** | `scan-R1-agent-identity` |
| **R1b** | 加密與簽章核心——簽憑證、簽通行證、連線加密 | 10 | 15 票全投完 | 通過 2 條，**範圍內零新問題** | `scan-R1b-crypto-core` |
| **R2a** | 工作怎麼派下去、狀態怎麼流轉 | 30 | 15 票全投完，**五條全部三票一致** | 通過 5 條，**範圍內零新問題** | `scan-R2a-task-dispatch` |
| **R2b** | 代理程式來拿檔案、雲端連回代理程式 | 13 | 15 票全投完 | 通過 4 條，**範圍內零新問題** | `scan-R2b-file-access` |
| **R3** | 我們主系統這端怎麼把它接上來 | 16 | 21 票全投完 | 通過 6 條，**範圍內零新問題** | `scan-R3-host-wiring` |

::: {.callout .ok}
**後面四輪「範圍內零新問題」不是白跑——那是好消息**

四輪從四個不同角度切進去，**都撞到同一個結論**。這代表問題不是散落各處，是**集中在同一件事**上，而且那件事被反覆驗證了四遍。

五輪一共通過 24 條發現，去重之後：**22 條反覆指向同一件事，2 條是檢視範圍外順手撈到的密碼外洩。**
:::

::: {.callout .warn}
**第一輪（R1）的覆核沒有完整跑成，這裡要說清楚**

那一輪放了 42 個檔案，超過負荷——負責覆核的程序全部超過用量上限被中斷，票沒投出來。**所以那一輪的結論是靠人工逐條開檔核對的**，不是靠自動覆核。

我們沒有因此重跑，而是**改用更小的範圍分四輪再查一遍**（就是 R1b／R2a／R2b／R3）。那四輪的覆核都完整跑完，而且都指向同一個結論——等於用四輪完整的覆核，補回了第一輪缺的那一次。

這也是「每輪不超過 15 個檔案」這條規矩的由來，詳見[檢視方法與工具](GUIDE-01-method-and-tools.html#batching)。
:::

::: {.callout .warn}
**這一頁在 2026-09-20 做過一次人工複查，推翻了幾條原本的寫法**

檢視工具產出的原始報告寫好之後，我們回到程式碼、版本紀錄與實機上逐條核對。結果有四條描述必須更正，另外查出**一條工具完全沒抓到的問題**（[撤銷只擋住一半](#revoke-half)）。

會更正的部分都在下面各條裡直接寫明「原本怎麼寫、實際是什麼」。**保留這些更正痕跡是刻意的**——稽核方要看得出我們核對過，而不是照單全收。
:::

---

## 問題一覽

**排序按風險，同風險的同一類排在一起。**「出事會怎樣」那欄講的是**業務影響**——誰受影響、損失什麼，不是技術現象。

::: {.callout .warn}
**讀這張表之前要先知道一件事：產品還沒有出貨給任何真實客戶。**

下面每一條講的「客戶會怎樣」，都是**產品上線之後會發生的事**，不是已經發生過的事。目前系統裡的資料全部是我們自己的測試資料。

**這不會讓任何一條變得比較不嚴重**——問題都是真的，只是還沒有人受害。**這一輪檢視正是為了在出貨前把它們處理掉。**

（**一個例外**：表裡凡是講「我們自己的文件網站／程式碼倉庫／測試機」的條目，與產品出不出貨無關——那些曝光是真的發生過的，已在各條裡標明。）
:::

| # | 問題 | 風險 | 分類 | 出事會怎樣（誰受影響） | 怎麼修 | 狀態 |
|---|---|---|---|---|---|---|
| **1** | 五條通訊管道全部不檢查對方是誰 | 🔴 **最嚴重** | 身分驗證缺失 | **客戶會失去對自己機房主機的控制權**——取走的是客戶自己的伺服器帳密，不只是我們系統的資料。且可冒充任一家客戶，**一家出事等於全部客戶暴露**；稽核證據可被偽造或抹除，**整份稽核報告的可信度會被質疑** | 呼叫者身分改由簽章證明，五條管道一起修，歸屬比對做進核心層；**同一批順便補上「這台是不是已被撤銷」** | ✅ **已修**（CM-2052） |
| **2** | 有一個入口會照著送進來的網址去打，不檢查那是不是自己人 | 🟡 中 | 身分驗證缺失 | **我們的系統可被當成探測客戶內網的跳板**——藉它試出客戶內網有哪些機器、哪些連得上。客戶的防火牆擋不住，因為流量是從他們自己信任的代理程式那一側發出的。**但要先有一個管理員帳號**，所以這是內部人越權，不是外人；而且只摸得到「機器在不在」，摸不到內容 | 那個入口改成**只收代理程式編號**，網址由後端自己查，不接受外部送網址 | ⬜ **未修**（工單 CM-1596） |
| **3** | 裝機啟用碼不會過期、也不限次數 | 🟡 中 | 憑證管理 | **外流的安裝文件或離職員工手上那組碼，永久有效**——整家客戶共用同一組，撿到的人隨時能登記一台自己的代理程式進來。**但這條的實際防護價值取決於第 1 條有沒有先修**（第 1 條沒修之前，攻擊者根本不需要用到這組碼） | **已拍板：碼本身維持現狀，改成看得見**——管理頁面顯示這組碼發出多久、用過幾次、上次何時被使用，見[下方](#enroll-code-options) | ⬜ **未修**（工單 CM-1597，修法已定） |

### 檢視範圍外另外撈到的三條

這三條跟遠端代理程式**沒有關係**——是工具在檢視時順手做了一次密碼掃描撈到的，掃描範圍涵蓋整個套件庫與文件站。列在這裡是為了完整，詳細歸在它們各自所屬的地方。

| # | 問題 | 風險 | 分類 | 出事會怎樣（誰受影響） | 怎麼修 | 狀態 |
|---|---|---|---|---|---|---|
| **4** | 共用基礎模組的一支設定檔（含一組資料庫帳密）被存進版本控制 | ⚪ 低 | 密碼外流 | **接觸過程式碼的人（含離職者、外包）都看得到那組帳密**。但實際可用性很低——那組帳密的主機值是「本機」，拿到的人只能拿它去連自己的電腦 | 從版本控制移除；確認沒有人在別處用同一組密碼 | ⬜ **未修**（工單 CM-1598） |
| **5** | 需求文件裡的資料庫超管密碼，曾自動發佈到公開網站 | 🟠 **高** | 密碼外流 | **在擋住之前，網際網路上任何人開網址就看得到**（統籌者親自開網址確認過）。那組帳號可繞過所有客戶隔離、讀寫每一家的資料 | 已擋住公開存取；**密碼已裁定不換**（只有測試機在用）；並在出貨流程加密碼檢查 | ✅ **已處理**（文件站已擋住公開存取、須先通過身分驗證；文件裡的密碼已全部改成指路文字，文件站建置時會自動擋下密碼字串（CM-2207）；三組帳密決策者裁定屬測試用、不換） |
| **6** | 舊版程式裡一把外部服務權杖從未撤銷 | 🟡 中 | 密碼外流 | **可用我們公司帳號的身分，讀寫外部平台上的專案與問題單**。拿得到程式庫歷史或舊版套件檔的人，一行指令就撈得出來 | 到該服務後台撤銷 | ✅ **已處置**（該權杖已撤銷，2026-09-20 確認） |

---

## 第 1 條：五條通訊管道全部不檢查對方是誰 {#cm1595}

::: {.callout .crit}
**這是整份報告唯一一件「最嚴重」等級的問題。**

其他所有問題至少都要「先有一個有效帳號」。**這一件不用。**
:::

### 問題是什麼

代理程式跟雲端之間有五條通訊管道。**五條都不問「你是誰」。**

程式碼裡有一行註解寫著「這裡不用檢查，因為外層的網頁伺服器會確認對方的身分憑證」。**但那道確認從來就沒有做出來過。**

::: {.callout .warn}
**這裡要更正原本的寫法**

原始報告寫的是「設定檔裡少了那一行」，會讓人以為是一時漏填、補上就好。**實際更根本**：

- 我們出貨的三份設定全部查過（一般版、落地版、測試版），**沒有任何一份曾經要求對方出示憑證**。
- 實機上兩台安裝版主機也查過，容器裡的設定同樣沒有。**安裝包那邊也沒有另外補上。**
- 而連線的運作方式是：**我們這端不開口要，對方就不會送。** 所以正確的描述不是「送來了沒人看」，是「我們從來沒開口要過」。

**真正發生的事**：寫程式的人假設「基礎設施那層會把關」，架基礎設施的人不知道有這個要求。**中間那道門，沒有人蓋。**
:::

### 為什麼這種事會發生

註解**不會被執行**，所以它永遠不會報錯。沒有任何機制會去檢查「註解裡寫的那個假設，到底有沒有成真」。

而且那段註解現在已經**過期了**：它提到的那個把關元件，在 2026-08-20 就整個退役了（代理程式外層的網頁伺服器被拿掉，相關邏輯收回代理程式自己承接）。註解卻還留在原地，一共四處。

**這不是資安漏洞本身，但它是漏洞能長期存在的原因**——下一個接手的工程師會照著這句話判斷「已經有人在把關了」，跟這次一樣。**修的時候要一併改掉。**

### 打進去能拿到什麼

| 管道 | 它原本的用途 | 打進去能拿到 |
|---|---|---|
| 報到 | 代理程式第一次安裝時登記 | 一張身分憑證 |
| **領工作** | 定期回來問「有工作嗎」 | 🔴 **整套稽核用的高權限通行鑰匙**（見下） |
| 確認收到 | 回報「我收到這份工作了」 | 搶走別台機器的工作 |
| **回報結果** | 回報「我做完了」 | 🔴 **偽造或抹掉稽核證據** |
| **下載檔案** | 來拿要掃描的源碼 | 🔴 **客戶上傳來掃描的源碼** |

::: {.callout .crit}
**「客戶自己機器的密碼」這句話講得太輕了——實際上不只是一組密碼**

代理程式回來領工作時，雲端會把**這家客戶全部七套檢測工具的連線設定**一併送過去。那裡面裝的是：

| 拿到什麼 | 能做什麼 |
|---|---|
| **Linux 主機的私鑰檔** | 免密碼直接登入被稽核的主機 |
| **Windows 的網域帳號** | 不是單一一台機器，是整個網域都認的帳號 |
| **掃描工具的存取金鑰** | 讀得到客戶交上來的原始碼、弱點掃描主機的管理權限、受測網站的登入身分 |
| **內部網路位址** | 連帶送出一份客戶的內網地圖 |

三件事讓它比「一組密碼」嚴重得多：

1. **用的是鑰匙檔、不是密碼**——客戶改密碼擋不掉，要一支一支換鑰匙。
2. **Windows 那把是網域帳號**——影響範圍是整個網域，不是一台機器。
3. **登進去就是管理員**——設定裡本來就開了提權，拿到就是主機的最高權限。

**這些是稽核用的高權限帳號，能登入被稽核的每一台主機。**
:::

### 而且可以冒充別家客戶

系統怎麼決定「這次動作算在哪一家客戶頭上」？

**它拿請求自己送上來的編號去查，查到是誰就切換成誰。**

可以用來冒充的編號有三種，全部由對方自己填：

| 編號 | 從哪裡取得 |
|---|---|
| 代理程式編號 | 任何登入的人在管理頁面上就看得到 |
| 機器編號 | 同一份範本複製出來的機器，這個值一模一樣 |
| 工作編號 | **那個不檢查身分的「領工作」管道，回應裡就會送給你** |

**三種都要堵，只堵一種等於沒堵。**

### 新發現：按下「撤銷」只擋住一半 {#revoke-half}

::: {.callout .crit}
**這一條是 2026-09-20 人工複查時查出來的，原始報告與跨模組總表都沒有。**

它不另開工單——**併進第 1 條的 CM-1595 一起修**，因為是同一套修法、同一層要補的東西。
:::

管理頁面上有一顆「撤銷」，管理員按下去之後那台代理程式會標成紅色的「已撤銷」。**但實際上只斷了一條管道。**

| 管道 | 撤銷後還進得來嗎 |
|---|---|
| 領工作 | ❌ 擋住了（有檢查「這台是不是已撤銷」） |
| **確認收到** | ✅ **照樣進得來**（完全沒有檢查） |
| **回報結果** | ✅ **照樣進得來**（完全沒有檢查） |

**所以被撤銷的那台機器，仍然可以：**

- **對任何一張工單回報結果——也就是仍能偽造稽核證據。**
- 在回報時附一個檔案編號，讓雲端去把那個檔案抓回來、存成這次檢測的稽核證據（**把自己準備的假檔案塞進客戶的案卷**）。
- 搶先「確認收到」別台機器的工單，干擾正常運作。

::: {.callout .warn}
**為什麼這比「根本沒有這顆按鈕」更糟**

管理員按下撤銷、看到紅色標籤，會合理認為「這台已經斷了」。**實際上它還能偽造稽核證據。**

**沒有那顆按鈕，反而比有一顆只做一半的按鈕安全**——前者不會讓人誤以為問題已經解決。

程式裡的註解寫撤銷之後「雲端所有資料面呼叫即拒」。**這句只對了一半**——它講的是「我們打去代理程式」那個方向；「代理程式打進來」這個方向只有領工作那一條補了檢查。

**這與第 1 條是同一個模式：想到了，只做了一部分就停了。**
:::

### 四個讓事情更嚴重的細節

這是五輪檢視陸續補上的，每一個都讓影響再擴大一層：

::: grid2
::: {.card .crit}
#### ① 授權過期也照樣打得到
系統有個「授權過期就轉成唯讀」的保護機制，但它的白名單**直接放行了整個代理程式的路徑**。授權過期的環境不會因此變安全。
:::
::: {.card .crit}
#### ② 雲端會主動去抓攻擊者指定的檔案
回報結果時可以附一個檔案編號，雲端會照著**去把檔案抓回來、存成這次檢測的稽核證據**。等於可以把自己準備的任何檔案，塞進客戶的稽核案卷。
:::
:::

::: grid2
::: {.card .warn}
#### ③ 管理頁面會把機器指紋送出去
等於免費奉送冒充用的第二把鑰匙。
:::
::: {.card .warn}
#### ④ 裝機啟用碼永遠有效
整家客戶共用同一組、不會過期。（這一條同時是上表第 3 條。）
:::
:::

### 為什麼評為最嚴重

| 判斷依據 | 這件事 |
|---|---|
| 要先有帳號嗎 | **不用**，完全不需要登入 |
| 拿得到什麼 | 客戶主機的**高權限登入鑰匙**（整套，不是一組密碼） |
| 只影響一家客戶嗎 | **不是**，可以冒充任何一家 |
| 能破壞稽核可信度嗎 | **能**，可以偽造、抹除、塞入假證據 |

**四項全中。**

而且拿走的**不是某一台機器的密碼，是客戶為了配合稽核而開給我們的高權限通行鑰匙**。客戶把鑰匙交給我們，是因為信任我們保管得住——這條要是被人用上了，失去的不只是資料，是這份信任本身。

### 一個有利的事實：憑證其實早就備齊了 {#cert-ready}

::: {.callout .ok}
**這件事會直接影響「該不該現在修」的判斷，所以要寫出來。**

原始報告只講了缺什麼，沒講已經有什麼。我們登入唯一一台有真代理程式在跑的機器（**我們自己的測試機——產品尚未出貨，客戶端一台都還沒有**），把它手上的憑證撈出來看：

| 查到什麼 | 內容 |
|---|---|
| 憑證齊不齊 | **三件套都在**——自己的憑證、私鑰、以及用來驗對方的根憑證 |
| 誰簽的 | **我們自己的簽發中心**（Guidant Agent CA） |
| 有效期 | **2026-09-03 ～ 2036-08-31（十年）** |
| 代理程式那端的設定 | 已經設成「完整驗證」模式——**客戶端那一半早就準備好了** |

**這代表什麼**：

1. **「補上驗證會把在跑的代理程式擋在門外」這個顧慮，不成立。** 兩層理由：一是憑證有效期到 2036 年，時間上根本不會過期；二是**產品尚未出貨，目前沒有任何客戶端的代理程式在跑**——現在補，不會影響到任何人。
2. 修法的難度從「從零建一套身分系統」降為「**把已經有的東西接上**」。
3. **現在是補這一層的最好時機**——出貨之後才改，要協調每一家客戶的機房；出貨前改，只是我們自己的事。
:::

### 但要先講清楚：補上雙向驗證，不等於修好 {#mtls-not-enough}

::: {.callout .warn}
**這是兩個不同的問題，雙向驗證只解得了一半。**

| 問題 | 雙向憑證驗證解得了嗎 |
|---|---|
| **你是不是一台合法的代理程式** | ✅ 解得了 |
| **你是哪一台、這份工作是你的嗎** | ❌ **解不了** |

它只確認「這條連線的另一端，手上有一張我們認可的憑證」。**它不會去比對「憑證上的名字，跟這個請求裡自己填的編號，是不是同一個」。**

**所以補完之後還剩下這個**：A 客戶的代理程式（憑證合法、驗證通過），在請求裡填上 B 客戶的代理程式編號，系統照樣切換成 B、**把 B 客戶主機的帳號密碼交給它**。

攻擊面從「網際網路上任何人」縮小到「任何一個有代理程式的客戶」，**但跨客戶偷資料仍然成立**。而落地版客戶的代理程式就裝在他們自己機房、憑證檔案在他們自己的硬碟上——**所以「客戶之間互相冒充」不是理論風險。**

**一個比喻**：雙向憑證驗證是**大門**，不是**房門鎖**。只裝大門不裝房門鎖，結果是外人進不來了，但**任何一個住戶可以進任何一間房**。
:::

### 建議怎麼修

::: {.callout .decided}
**第一步要決策者拍板：用哪一種身分證明**

兩條路，**選一條當主軸、另一條最多當輔助**：

| 方案 | 怎麼運作 | 優點 | 代價 |
|---|---|---|---|
| **短效通行證**<br>（建議） | 平台本來就會簽發這種通行證，讓代理程式每次呼叫都帶上 | **產品本身就有這個機制，不必動客戶的基礎設施**；我們自己驗得了，客戶怎麼架都不受影響 | 要處理通行證的發放與更新 |
| **客戶端憑證** | 由最外層的網頁伺服器確認對方憑證，驗過的身分往後傳 | 連線層就擋掉；而且[憑證早就備齊](#cert-ready)，接上的成本比原先估的低 | 要改客戶機房的設定，落地版客戶各自裝機、改動成本高；而且[它只解一半](#mtls-not-enough)——證明「你是一台登記過的機器」，不證明「這張工單是你的」 |

**建議走短效通行證**——不用碰客戶端的設備。客戶端憑證可以之後再補，但**不能拿它當唯一手段**。
:::

**後續四步**：

| 步驟 | 做什麼 | 為什麼不能省 |
|---|---|---|
| **二** | 五條管道一起掛上驗證，身分從驗過的通行證推出來，**不再讀請求裡自報的編號** | 只修其中幾條，剩下的還是門戶洞開 |
| **三** | 「這張工單是不是你的」做成核心層的必要條件 | 只在最外層加一道檢查，日後多一條呼叫路徑（批次補登、維運工具、修復腳本）就會再繞過一次 |
| **四** | **同一層順便補上「這台是不是已被撤銷」** | 目前三條管道只有一條有查，[撤銷等於只做了一半](#revoke-half)。既然要動這一層，一起補的邊際成本接近零 |
| **五** | 最外層補上客戶端憑證確認 | **只是連帶，不能取代第三步** |

### 修完之後擋得到誰、擋不到誰 {#fix-coverage}

上面五步做完，不是「從此安全」，也不是「做了也沒用」。**擋得到的和擋不到的，要先講清楚，免得事後有落差。**

| 誰 | 修完後 |
|---|---|
| 網路上的外人 | ✅ **擋掉** |
| A 客戶冒充 B 客戶 | ✅ **擋掉** |
| 被按過「撤銷」的那台機器 | ⚠️ 要**一併補上第四步**（確認收到、回報結果那兩條）才擋得掉——[目前只做了一半](#revoke-half) |
| 客戶機房裡那台機器本身 | ❌ **照樣拿得到——這是設計本身，不是缺陷** |

::: {.callout .warn}
**最後一列要特別說明：那不是沒修好，是本來就該這樣**

代理程式要去登入客戶的主機做掃描，**就一定得拿到那些登入鑰匙**——不給它，它什麼事都做不了。所以這些鑰匙送到代理程式手上，是這套設計的必要前提。

補完之後的差別在於：**從「網路上任何人打得到就拿得到」，變成「只有真的那台代理程式拿得到」**——而那正是設計原本想要的樣子。

但那台代理程式就裝在客戶自己的機房裡。**能實際碰到那台機器的人，仍然撈得出裡面的東西。**
:::

**所以結論是**：補完之後，風險範圍從「**網路上任何人**」縮小到「**能實際碰到那台機器的人**」。後者客戶本來就承擔著——那些鑰匙是客戶自己提供給我們的，也存在他們自己的機房裡。**前者才是我們必須負責關掉的那一半。**

---

## 第 2 條：有一個入口會照著送進來的網址去打（中） {#cm1596}

::: {.callout .warn}
**這裡要更正原本的寫法**

原始報告寫的是「產品有個測試連線功能，讓管理員確認能不能連上某台主機，但它沒有限制可以連去哪裡」——這會讓人以為畫面上有個表單讓管理員自己填網址。**實際查前端，沒有那個表單。**

畫面上是「遠端代理程式管理」清單裡的一欄，標題叫「健康檢查」，顯示上線／離線。**頁面一載入就自動對清單上每一台探測一次**（旁邊另有一顆重新探測的按鈕）。**網址一律是從資料庫讀出來的，所以照畫面正常使用完全安全。**
:::

### 問題在哪裡

問題不在畫面，**在後端那個入口本身**：它收到什麼網址就打什麼，**不檢查那是不是自己人的機器**。

不必透過我們的畫面——用工具直接對那個入口送一個自訂網址，它照樣會打過去。

::: {.callout .warn}
**「畫面上不能填」不構成防護**

前端跑在使用者自己的瀏覽器裡。任何人打開瀏覽器的開發工具，就看得到我們的畫面送了什麼請求；複製下來改掉網址重送即可。

**前端擋不住任何東西。真正的守門一定要在後端。**
:::

### 但這條的前提是「要先有管理員帳號」

這是它與第 1 條最關鍵的差別，必須講清楚，否則讀者會以為兩條一樣嚴重。

| | 第 1 條 | 第 2 條 |
|---|---|---|
| 要先有帳號嗎 | **不用** | **要**——而且要登入、有授權、有管理能力，三關都過 |
| 拿得到什麼 | 客戶主機的明文帳密 | **只有「那台機器在不在、連不連得上」**，拿不到內容 |
| 誰會是那個人 | 網際網路上任何人 | 有管理員帳號的內部人或外包 |

**所以這是「內部人越權」，不是「外人闖入」。** 這也是它從原本的「高」調整為「中」的理由（與工單 CM-1596 的評級一致）。

### 修法定案：收編號，不收網址 {#item2-fix}

::: {.callout .decided}
**決策者已拍板：不是「檢查網址」，是「不收網址」。**

原本的修法寫的是「限制可連線的目標範圍，只允許連向已登記的檢測目標」。**改成更徹底的做法**：

**那個入口改成只收代理程式編號，網址由後端自己從資料庫查出來。完全不接受外部送網址。**

| 為什麼比「檢查網址」好 | |
|---|---|
| **檢查有可能寫漏寫錯** | 網址的寫法變化很多，只要比對規則有一點沒想到就會被繞過（例如只比對開頭，`https://好的網址@壞的網址` 這種寫法就過了） |
| **不收就沒得騙** | 這是**消除選擇**，不是**增加檢查**。沒有可以被寫錯的比對規則，就沒有可以被繞過的比對規則 |

**更深一層的理由**：現在的形狀是「前端送什麼、後端打什麼」，等於「決定要打去哪」這個權力**落在前端手上**。而前端跑在使用者的瀏覽器裡——**等於落在任何一個會用開發工具的人手上**。改成收編號之後，這個決定權整個收回後端。

**施工牽動**：前端要跟著改成送編號，是前後端一起動的小工程。開工前要先確認沒有別的地方在用這個入口。
:::

---

## 第 3 條：裝機啟用碼不會過期、也不限次數（中） {#cm1597}

### 先澄清它是什麼：是入場券，不是員工證

::: {.callout .warn}
**這裡要更正原本的寫法**

原始報告把它寫成「報到用的通行碼」，容易讓人以為它是一組長期有效的存取金鑰（像某些平台給的個人金鑰那樣）。**它不是。它是「裝機啟用碼」，只在安裝當下用一次。**

完整的生命週期是：

| 步驟 | 發生什麼 |
|---|---|
| 1 | 裝機時把啟用碼填進去 |
| 2 | 代理程式拿它去報到——**這一步只發生一次** |
| 3 | 雲端當場簽發一張身分憑證給它 |
| 4 | **之後一律用憑證，啟用碼再也不會出現** |

實查代理程式後續每次報到送出的內容，確實**完全沒有帶啟用碼**——只帶自己的編號、機器編號、狀態、版本與能力。

**所以它是入場券，憑證才是員工證。啟用碼外流，不影響已經裝好的代理程式。**
:::

### 描述本身是對的

- 存放這組碼的資料表**確實沒有到期欄位、也沒有使用次數欄位**。
- 驗證的那段程式**確實是查到就放行**，沒有任何時間或次數檢查。
- **確實是一家客戶共用一組**——產生新碼時會把該客戶既有的碼全部停用，永遠只有一組有效。

### 最值得注意的一點：鎖裝在唯一沒人走的那扇門上

四條進得來的管道裡，**只有「報到」這一條在檢查東西**（檢查啟用碼）。

而報到，**正是攻擊者唯一不需要走的那一條**——因為[第 1 條](#cm1595)讓他可以直接打「領工作」。

**這解釋了為什麼這條看起來怪**：防護做了，但做在唯一沒人經過的門上。也因此，**這條的實際防護價值，完全取決於第 1 條有沒有先修**。第 1 條沒修之前，這條的價值接近零。

### 設計沿革：這是刻意的取捨，不是遺漏

查版本紀錄與當初的設計文件（2026-06）：

| | |
|---|---|
| **當初要解決什麼** | 自動化裝機——把「管理員在網頁上一台一台手打代理程式網址」那一步拿掉，改成**機器自己來登記，報到時當場簽發憑證** |
| **為什麼還需要這組碼** | 機器自己來登記，總得有東西告訴系統「它是哪一家客戶的」。**這組碼真正承擔的是歸屬判定，不只是門票**——所以不能直接拿掉 |
| **當初知不知道有上限** | **知道。** 設計文件裡有一節標題就叫「安全上限（誠實）」，自己寫明：機器指紋是代理程式自己回報的，擋得住一般的憑證盜用，**擋不住「完全控制那台機器又改掉程式來偽造指紋」** |
| **「不審核」是誰決定的** | 設計文件明寫「新設備自動登記不審核」——**這是當時刻意的取捨** |

### 處置定案：維持現狀，但改成看得見 {#enroll-code-options}

::: {.callout .decided}
**決策者 2026-09-20 拍板：碼本身不動，加上「看得見」。**

**定案內容**：

- **碼維持現狀**——不加有效期限、不改成單次使用、不加後台審核、不做一機一碼。
- **但要讓它看得見**：管理頁面顯示這組碼**發出多久了、用過幾次、上次什麼時候被使用**。有人動過，管理員看得出來。

**為什麼這樣選**：

| 理由 | 說明 |
|---|---|
| **保管責任在客戶身上** | 跟某些開發平台把個人金鑰交給使用者自己保管是同一個模式。決策者 2026-09-17 已就此推翻過「加期限」的建議，這次的判斷一致 |
| **加期限會卡住兩個真實情境** | 「碼發出去了但客戶還沒去裝機」、「一次要裝好幾台」——兩種都是正常用法，不該被擋 |
| **另外兩個方向會推翻當初的設計目標** | 後台審核與一機一碼都會把裝機流程變麻煩，而**自動化裝機正是 2026-06 當初要解決的問題**。選它們等於把當初解掉的麻煩再帶回來 |

**考慮過但沒有選的兩個方向**（留著，供日後回頭檢視）：

| | 做法 | 好處 | 為什麼沒選 |
|---|---|---|---|
| **② 後台審核** | 機器來登記後先進待審清單，管理員核准才發憑證 | 把「這台是不是我們家的」這個判斷，交回給看得到全局的人 | 等於推翻 2026-06「不審核」那個決定，把當初想解決的裝機麻煩帶回來 |
| **③ 一機一碼** | 管理員先在後台建一台，系統產生只屬於那一台的碼 | 碼外流只影響一台 | 一次要裝很多台時會非常煩 |

**「2026-06 那個『不審核』的取捨，現在還成立嗎」——已答：維持成立。** 自動化裝機的需求沒有改變，這次的拍板就是對這個問題的回答。

**要提醒的一點**：選①的代價是「**要有人去看才有用**」。顯示出來之後，還得有人定期去看那三個數字，否則等於沒做。這一點在排期時要一起想清楚由誰負責。
:::

::: {.callout .warn}
**定案不代表這條可以先做。**

這條的實際防護價值仍然**完全取決於第 1 條有沒有先修**——第 1 條沒修之前，攻擊者根本不必走報到這條路，直接打「領工作」就好，這組碼看不看得見都不影響他。**排期上第 1 條在前。**
:::

---

## 第 4 條：共用基礎模組的一支設定檔進了版本控制（低） {#cm1598}

::: {.callout .warn}
**這裡要更正原本的寫法**

原始報告寫「模組的設定檔（含密碼）被存進版本控制」，讀者會以為是**遠端代理程式自己的**設定檔。**不是。**

那是套件庫裡一支**共用基礎模組**的設定檔（`jedi-common/.env`），**跟遠端代理程式沒有任何關係**。它會出現在這一頁，純粹是因為檢視那一輪時工具順手做了一次密碼掃描，**掃描範圍涵蓋整個套件庫**。

所以它歸到上面的「檢視範圍外另外撈到」那張表，詳細歸屬於該模組。
:::

### 實際風險比原先評的低很多

| 查證項目 | 結果 |
|---|---|
| 什麼時候進去的 | 2025-04-16，**建立那個套件時一起放進去的，之後沒有再改過** |
| 有程式在讀它嗎 | **沒有。** 整個套件庫搜過，沒有任何程式載入這支檔——**它不在任何執行路徑上** |
| 那組帳密能連到哪 | 主機值是「本機」。**拿到的人只能拿它去連自己電腦上的資料庫** |
| 忽略清單有設嗎 | **有。** 規則早就在了，只是這支檔在規則生效前就已經進去了 |
| 還有別的嗎 | **整個套件庫只有這一支**，其他同類檔案都被規則擋掉了 |

**所以建議由「中」降為「低」**（與工單 CM-1598 的評級一致）。

### 修法簡化為兩步

| 步驟 | 做什麼 |
|---|---|
| **一** | 從版本控制移除這支檔 |
| **二** | 確認沒有人在別的地方用同一組密碼 |

**不必做的兩件事**，以及為什麼：

- **不必換密碼**——除非第二步查出這組密碼在別處被重複使用。
- **不必清歷史紀錄**——那組值本身沒有用處（只連得到本機），清歷史的成本遠大於收益。
- **不必「加入忽略清單」**——規則已經在了。

### 但它真正的意義在別的地方

::: {.callout .warn}
**這支檔躺了一年半沒人發現**，是這次的密碼掃描把它撈出來的。

**真正的問題不是這支檔，是我們過去沒有在出貨流程裡自動檢查「有沒有密碼被上傳」。**

這一點與[第 5 條](#item5)（發到公開網站的資料庫密碼）是**同一個根因**——兩次都是靠人工掃描才發現，而不是流程自動擋下來。
:::

---

## 第 5、6 條：範圍外那兩條的狀態更新 {#item5}

### 第 5 條：發到公開網站的資料庫密碼——已處理

::: {.callout .warn}
**狀態：已處理。**

**先講清楚一件事**：這一條與「產品有沒有出貨」**完全無關**。曝光的是**我們自己的文件網站**，不是隨產品交出去的東西——**曝光是真的發生過**，統籌者親自開網址確認過。嚴重性維持原評級，不因任何後續裁定而降低。

**緩解方式**：已用 Cloudflare Zero Trust 擋住那個文件站的公開存取——現在要先通過身分驗證才進得去，網際網路上的任何人不再開網址就看得到。**決策者裁定：不列為緊急項目。**

**密碼要不要換——已裁定：不換。**

| | |
|---|---|
| **裁定** | 決策者 2026-09-20 裁定**不更換**這組密碼 |
| **理由** | **那組帳密只有測試機在用**，不是隨產品出給客戶的東西，換發的收益極低 |
| **不是新決定** | 跨模組總表早就寫著「測試機專用的資料庫與系統管理帳號密碼不需要更換（因為只有測試機在用）」——**這次是同一裁定的再次確認**。之前口頭講過多次但沒有落進文件，這次固化下來 |

**根因那件事也已經處理：**

| | 根因那件事 | 現況 |
|---|---|---|
| **一** | **出貨流程要加自動密碼檢查**——這次的出口是文件站，**下次可能是別的出口**，擋住一個出口不等於解決根因 | ✅ **已做**（CM-2207）：文件與腳本裡的測試帳密已改成指路文字、公開文件站重建，文件站建置時會自動擋下密碼字串；決策者 2026-09-26 再次確認三組帳密屬測試用、不換 |
:::

### 第 6 條：外部服務權杖——已處置，結案

::: {.callout .ok}
**狀態已從「未修」改為「已處置」。決策者確認該權杖已撤銷。**

查證過程留個痕，供日後追溯：逐一掃過版本紀錄後確認**有兩把不同的權杖**——一把在另一個套件的設定檔裡（已在工單 CM-1573 處理完畢），另一把是**寫死在三支程式碼裡**的，最早出現在 2025-06-10。原始報告指出的「從未撤銷」是後面這一把，**已確認撤銷**。
:::

---

## 仍待決策的兩件事 {#pending}

::: {.callout .pending}
**這些本頁不下結論，列出來等決策。**

| | 待決的事 | 目前手上的判斷依據 |
|---|---|---|
| **一** | **出貨流程加自動密碼檢查，排在什麼時候** | 這與第 4、5 條是同一個根因——兩次都是靠人工掃描才發現，不是流程自動擋下來的。待決策者與 PM |
| **二** | **第 1 條選哪一種身分證明**（短效通行證／客戶端憑證） | 分析上建議走短效通行證（不必動客戶的基礎設施）。但[憑證早就備齊](#cert-ready)這個新事實，降低了客戶端憑證那條路的成本，可以重新評估。詳見[上方](#cm1595) |
:::

### 這一輪結掉的兩件

::: {.callout .decided}
**原本列在這裡待決、2026-09-20 已拍板的兩件，記錄在此供稽核對照——不是憑空消失。**

| 原本待決的事 | 裁定結果 |
|---|---|
| **第 3 條要走哪一個方向**（看得見／後台審核／一機一碼） | **選①：碼維持現狀，改成看得見。** 連帶答覆「2026-06 那個『不審核』的取捨現在還成不成立」——**維持成立**。理由見[上方](#enroll-code-options) |
| **[第 5 條](#item5)那組資料庫密碼要不要換、何時換** | **裁定不換**，理由是那組帳密只有測試機在用。這是既有裁決（跨模組總表早已載明）的再次確認，見[上方](#item5) |
:::

---

## 這塊的結論

::: {.callout .crit}
**一句話**：這塊只有一件大事，但那一件是全案最嚴重的——**而且工單早就開好躺著，不是被遺漏，是等統一排期。**

**現在修，成本最低**：產品尚未出貨，代理程式一台都還沒進到客戶機房。這幾條全部是**在我們自己手上就能改完**的；出貨之後才動，每一個改動都要去協調客戶的機房。

**建議**：

1. **第 1 條應該優先處理。** 它是整份報告中唯一「不需要任何帳號就能得手」的問題，拿得到的是客戶主機的明文密碼——**那是客戶自己的資產，不只是我們的**。而且[憑證早就備齊](#cert-ready)，修起來比原先估的容易。
2. **修第 1 條時要連[撤銷只擋一半](#revoke-half)一起補**——同一層、同一批，邊際成本接近零。不補的話，管理員會繼續誤以為撤銷已經斷了那台。
3. **第 1 條與第 2 條可以一起做**（同一套身分驗證改造涵蓋得到）。**第 3 條要等第 1 條修完才有意義**——修法雖已拍板（改成看得見），但第 1 條沒修之前，那組啟用碼的防護價值接近零。
4. **第 4 條與其他模組的密碼外流屬於同一類**，建議併在一起處理，並把「出貨流程加自動密碼檢查」當成這一類的共同修法。

**要提醒的一件事**：第 6 條已處置、第 5 條已處理，但**這兩條都是檢視範圍外順手撈到的、屬於我們自己的基礎設施，不是這塊的核心問題**。這塊真正的四條（第 1～4 條）**一條都還沒動**。

**最後一句話要講清楚**：產品還沒出貨，代表這些問題**還沒有傷害到任何人**——但**不代表它們不嚴重**。每一條都是真的，出貨之後就會是真實客戶的風險。這一輪正是為了在那之前把它們處理掉。
:::

| 統計 | |
|---|---|
| 檢視輪數 | 5 輪、99 個檔案 |
| 通過的發現 | 24 條（去重後 3 條屬於本模組、3 條屬於範圍外） |
| 人工複查新增 | **1 條**（[撤銷只擋一半](#revoke-half)，併入 CM-1595 修） |
| 最嚴重 | 1 條 |
| 已處置 | 1 條（第 6 條） |
| 已處理 | 1 條（第 5 條：文件已清、建置加密碼檢查；密碼經裁定不換） |
| 已修 | 1 條（第 1 條，CM-2052） |
| 未修 | 3 條（第 2～4 條） |
| 已開工單未排期 | 3 張（CM-1596～1598） |
| 修法已拍板 | 2 條（第 2 條收編號、第 3 條改成看得見） |
| 仍待決策 | 2 件（見[上方](#pending)） |

---

| 你想知道 | 看哪裡 |
|---|---|
| 我們用什麼方法查、結果有多可信 | [檢視方法與工具](GUIDE-01-method-and-tools.html) |
| 其他模組的檢視結果 | [回總報告首頁](index.html) |
