---
title: R3 檢查結果：主專案宿主接線與資料面 adapter（BE repo）
---

# R3 檢查結果：主專案宿主接線與資料面 adapter（BE repo）

> 檢查日期 2026-09-17｜對應卡片 CM-1594｜檢查範圍 16 個檔案

## 🔴 一句話結論

**六條發現全部通過檢查——三條嚴重、三條中等——但在本棒指定的檢查範圍內，一條新問題都沒有。** 三條嚴重與三條中等分別對應到先前已經開好的修正卡（CM-1595）與跨 arc 總表既有的項目（CM-1629、總表第 3 項），**範圍內淨新增 0**。

**真正的新東西來自範圍外**：工具在順手做的密碼掃描裡撈到一條，把一個既有問題升級了——**寫在需求文件裡的資料庫超級管理員密碼與兩組登入帳號密碼，已經被發佈到任何人都打得開的公開文件網站上**。原本 CM-1629 的前提是「拿得到程式碼倉庫的人才看得到」，現在變成「任何人，不用帳號、不用內網、用瀏覽器就看得到」。首腦 2026-09-17 11:45 **親自打開那個公開網址確認過**：頁面存在、密碼字串在上面、四個帳號名可見。這條登記為跨 arc 總表 §3.1 的**新項第 84（高）**。

**這一棒也是 FR-077 五棒的最後一棒**——套件本體（R1／R1b／R2a）、借用的檢測套件（R2b）、以及本棒的主專案宿主接線，整條遠端代理程式控制鏈到此全部掃完。

## 這一棒在檢查什麼

前面四棒看的都是套件本身（`jedi-remote-agent`／`jedi-detection`）。本棒換一個角度：**主專案（BE repo）是怎麼把那個套件接上來的**。套件自己不決定誰能進門，它把守門這件事交給宿主；宿主接得對不對、有沒有在接線的地方自己開後門，只有看主專案這邊才知道。具體四件事：

1. **管理端點的守門殼**——主專案傳給套件的那個 `admin_required` 函式，到底檢查了什麼、順序對不對、會不會漏掛。
2. **代理程式下載檔案的那條路由**——這條是主專案自己手動掛上去的，不走套件的路由表。
3. **資料面 adapter**——雲端主動連回客戶機房的代理程式時，那層轉接程式怎麼決定要打哪一台、要打什麼路徑。
4. **依賴注入與對帳查詢**——註冊進容器的那幾支 repository 有沒有跨請求殘留狀態、對帳查詢有沒有客戶隔離。

掃描目標 `~/Projects/Billows/Audit-Manager/compliance-manager-be`（scanRoot 是 BE repo），revision `4bf687c0`（branch `feature/review`，**工作區有未提交改動故驗證章標 `-dirty`**，那些改動屬於別條線、不在本棒範圍內），mode `scan`，effort `low`，focus `attack-surface`。範圍是 16 個受版控的 Python 檔：管理端點守門、代理程式檔案下載路由、認證設定、雲端對代理程式的資料面 adapter、任務付載提供器、對帳查詢、兩個依賴注入容器。**這 16 檔從 `4bf687c0` 到現在的 HEAD 零漂移**，所以報告裡的行號現在打開還是對的。

## Coverage

16 個檔以單一元件讀完。低強度跑法不做元件盤點、不做威脅建模、不跑額外的廣度掃描，`completenessCheckOutcome` 為 `not-applicable`（指定範圍的掃描本就不適用）。**這份報告完全不能拿來說主專案其他地方沒事**，它只涵蓋「遠端代理程式接線」這一小塊。

派出兩位研究員、兩位都回報。驗證跑一輪，8 個原始候選去重後 7 個，每一條都拿到完整的三票，**21 票全投出，沒有候選遺失、沒有候選未被審、沒有候選被交到下一輪**。六條通過、一條（F7）被三票一致駁回。面板調低了兩條的嚴重度：F4 與 F5 都從研究員原報的嚴重降為中等，本報告維持降後的結果。

**六條裡有三條的位置在範圍外**（F1、F3、F6）。因為設了攻擊面 focus，工具會順手跑一輪密碼掃描，這三條全部是那輪撈到的——分別落在文件產生腳本、需求文件、安裝程式的資料庫初始化腳本，都不是遠端代理程式的宿主接線。研究員為了看懂脈絡也讀了範圍外的東西（`.venv/` 裡裝好的兩支套件、`common/authz/`、前端 repo 裡出貨的 nginx 設定），那些閱讀讓 F2／F4／F5 判得起來，但沒有任何一條發現是記在那些樹上的。

**這份報告沒有逐檔紀錄**：`coverage.research` 是 `null`，工具沒留下「哪位研究員把哪個檔讀到什麼程度」的帳。下方「卡片重點逐項」段由首腦逐項開檔補查，並標明哪些是工具報的、哪些是人工查的。

工具沒有實際執行任何程式碼：沒跑測試、沒發請求、沒示範攻擊。六條發現全部是讀原始碼推出來的。

## 掃到什麼（總覽）

| # | 嚴重度 | 這是什麼問題（白話） | 出事會怎樣 | 要先有什麼才打得到 | 位置 | 修正卡 |
|---|--------|---------------------|-----------|------------------|------|--------|
| [F1](#f1) | 🔴 嚴重 | POC 資料庫的帳號密碼寫死在一支文件產生腳本裡（⚠️ 越界） | 拿得到程式碼的人可直接連進 POC 資料庫；POC 依規定等同正式環境 | 拿得到程式碼倉庫＋連得到內網 | `docs/system-design/scripts/generate_db_schema_docx.py:34` | ✅ 已修（CM-2048／CM-2207；原卡 CM-1629 作廢；SUMMARY M01-5） |
| [F2](#f2) | 🔴 嚴重 | 心跳回應裡夾帶已經解密的明文帳號密碼，而心跳端點不檢查來人是誰 | 拿走客戶自己機器的帳密（SonarQube 權杖、SSH／WinRM 帳密） | 連得到 API＋知道一個代理程式編號或機器編號 | `infra/remote_agent/adapter/detection_task_payload_provider.py:68`（解密在 `:124`） | ✅ 已修（CM-2052） |
| [F3](#f3) | 🔴 嚴重 | 資料庫超管密碼與兩組登入帳密寫在需求文件裡，而那份文件**已經發佈到公開網站**（⚠️ 越界） | 任何人不用帳號、用瀏覽器就讀得到；拿到超管密碼即繞過所有客戶隔離 | 一個瀏覽器 | `docs/features/FR-026-2605-project-flow-engine-integrate/03-ap-binding/implementation-plan.md:33` | ✅ 已處理（文件站已擋公開存取、密碼改指路文字、建置時自動擋密碼字串 CM-2207；三組測試帳密裁定不換；SUMMARY M01-5） |
| [F4](#f4) | 🟡 中等 | 代理程式下載檔案的那條路由，身分只靠請求標頭上自己寫的一行字（授權面） | 下載走客戶上傳來掃描的源碼壓縮包，且可跨客戶 | 連得到 API＋知道一組代理程式編號與檔案編號 | `api/remote_agent/routes/agent_file_route.py:49` | ✅ 已修（CM-2052） |
| [F5](#f5) | 🟡 中等 | 同一條路由，從「根本沒有身分驗證」這一面看（認證面） | 同 F4 | 同 F4 | `api/remote_agent/routes/agent_file_route.py:48` | ✅ 已修（CM-2052） |
| [F6](#f6) | 🟡 中等 | 每一套安裝出來的系統，原廠管理員都是同一組密碼（⚠️ 越界） | 知道那組密碼的人，可以登入任何一家客戶的系統當平台超級管理員 | 取得原廠密碼（內部文件外流、離職員工、或離線破解雜湊） | `scripts/init/06-admin.sql:41` | 🚫 裁定不修（SUMMARY M01-3，落地版僅內網可達） |

**範圍內淨新增 0；越界撈到 1 條升級事實**——第 84 項（公開文件站洩露資料庫超管密碼與兩組登入帳密）。跨 arc 總表 §3.1 加一項。

## Findings

<a id="f1"></a>
### F1 — POC 資料庫密碼寫死在文件產生腳本裡（嚴重，3:0，⚠️ 越界）

**這是什麼問題。** 一支用來產生資料庫結構說明文件的 Python 腳本，把 POC 環境的應用程式帳號（`cm_app`）與它的密碼直接寫成程式碼裡的字串，跟著程式碼一起進了版控。

**出事會怎樣。** 任何拿得到這份程式碼的人（外包、離職員工、CI 取出的副本、外流的壓縮檔），只要連得到內網那個網段，就能用 `psql` 直接連進 POC 資料庫。POC 依專案自己的規定**等同正式環境**（對外展示、客戶試玩）。而且同一把密碼還被文件記載為 DEV、STG 以及那個會繞過客戶隔離的超管帳號 `cmmgr` 共用——一次外洩等於全環境打開。

**要先有什麼才打得到。** 拿得到程式碼倉庫的任一份副本；連得到內網那個網段（在公司網路或有 VPN／跳板）；密碼自提交以來沒換過。

**在哪裡。** `docs/system-design/scripts/generate_db_schema_docx.py:34`。

**怎麼修。** 換密碼（值已在版控歷史裡，改檔案救不回來），腳本改成從環境變數讀，並加上提交前的密碼掃描擋住再犯。

**驗證。** 3/3 三位檢查員一致確認成立。

**首腦核對註記與判定。** ⚠️ **越界發現**——這支腳本住在文件產生工具樹底下，不是遠端代理程式的宿主接線。首腦開檔核對過**這一支確實就是 CM-1629 那 249 個檔裡的其中一支、同一把密碼**（比對只看前綴，明文不記錄），**不另計新項**；已補進 CM-1629 卡的「腳本類落點」——原本那張卡的清單偏重對話紀錄與需求文件，這次確認**可執行的腳本也是落點之一**，清理時要一起掃。

<a id="f2"></a>
### F2 — 心跳回應夾帶解密後的明文帳密，而入口不檢查身分（嚴重，3:0）

**這是什麼問題。** 主專案這支「任務付載提供器」負責準備要發給代理程式的工作內容。準備的過程中，它會把該客戶儲存的檢測工具憑證**從加密狀態解開成明文**，放進要回傳的內容裡。而這包內容最後是經由套件的心跳端點吐出去的，**那個端點不檢查來人是誰**——伺服器判斷「你是哪一台」的唯一依據，就是請求內容裡自己寫的代理程式編號或機器編號。

**出事會怎樣。** 回傳的內容裡有客戶自己基礎設施的帳號密碼：SonarQube 的存取權杖、客戶主機的 SSH 與 WinRM 帳密。拿到的人可以直接登入客戶自己的機器——**波及範圍超出我們的產品之外**。

**要先有什麼才打得到。** 連得到 `/api/1.0/agents/heartbeat`；知道一個代理程式編號或一個機器編號（後者在同一份 VM 樣板複製出來的機器上是一樣的）；該代理程式當下至少有一筆待辦工作，且那個工具的設定裡有存憑證。程式碼註解裡宣稱身分是由外層 nginx 的用戶端憑證驗證來保證的，**但出貨的 nginx 設定檔一行都沒有配置**。

**在哪裡。** `infra/remote_agent/adapter/detection_task_payload_provider.py:68`（`DetectionTaskPayloadProvider.build_pending_payloads`），解密動作在同檔 `:124`（`_resolve_tool_credentials`）。入口是套件那側的 `AgentHeartbeatRoute.post`。

**怎麼修。** 在收件人的身分被密碼學方法證實之前，不要吐出解密後的憑證。心跳要先驗過身分（用驗過的用戶端憑證主體，或平台本來就會簽的短效通行證），並且從驗過的那個值推出代理程式身分，而不是相信請求內容裡自報的編號——這件事要在走到這支付載提供器之前就擋住。

**驗證。** 3/3 三位檢查員一致確認成立。

**首腦核對註記與判定。** 屬實，**重複 CM-1595，不另計。**

**這是同一件事的第四次獨立確認**：R1 的研究員報過一次、首腦 2026-09-16 比對那筆修改的前後核過一次、R2a 面板 3:0 再確認一次、本棒從**宿主側的終點**又看到一次。前三次看的都是套件那一端的入口，這次看的是主專案這一端「明文帳密到底是在哪一行生出來的」——**兩端都確認了，這條沒有翻案空間**。

<a id="f3"></a>
### F3 — 資料庫超管密碼與登入帳密寫在需求文件裡，而那份文件已被發佈到公開網站（嚴重，3:0，⚠️ 越界）

**這是什麼問題。** 一份需求文件的「環境前置」段落，把資料庫超管帳號 `cmmgr` 的密碼、以及兩個產品登入帳號（`blsadmin`、`blsit`）的密碼寫在裡面。這本身是 CM-1629 已知的老問題。**新的部分是它的所在位置**：這份文件在 `docs/features/` 底下，而那個目錄**每次推上主線就會自動部署到公開的文件網站**，文件也會被轉成網頁。

**🔴 首腦 2026-09-17 11:45 親自打開那個公開網址確認**——`https://guidantai-feature-doc.jedicotech.com/FR-026-2605-project-flow-engine-integrate/03-ap-binding/implementation-plan.html`：**頁面存在、含有密碼字串、四個帳號名可見**。不是推測，是實際打開看到的。

**出事會怎樣。** `cmmgr` 是那個會繞過客戶隔離的資料庫超管等級帳號，拿到它等於對所有客戶的資料可讀可寫、隔離機制形同不存在。另外兩組是真的能登入產品的帳號密碼。

**這條真正的意義是「前提被升級了」。** CM-1629 原本的前提是「**拿得到程式庫的人**才看得到」——所以緊急度還可以用「範圍有限」來衡量。現在的前提是「**任何人，不需要任何帳號、不需要在內網，用瀏覽器就看得到**」。這是性質改變，不是數量增加。

**規模。** `docs/` 底下 **181 支 md、65 支 html** 含有那把資料庫密碼（用 `grep -rl` 數出來的檔案數）。這一支只是其中被確認「已經發佈出去」的那一支。

**要先有什麼才打得到。** 一個瀏覽器。沒有其他條件。

**在哪裡。** `docs/features/FR-026-2605-project-flow-engine-integrate/03-ap-binding/implementation-plan.md:33`，「環境前置」段。

**怎麼修。** 三件事都要做：**換密碼**（`cmmgr`、`cm_app` 與那兩個登入帳號——值已經在版控歷史裡、也已經在靜態網站上，改檔案不構成補救）、**清掉 `docs/` 底下所有含密碼的檔**、**重新產生並佈署文件網站**（不重佈的話網頁還是舊的）。另外建議在文件站的建置流程加一道檢查，只要有檔案出現密碼樣式就讓建置失敗。

**驗證。** 3/3 三位檢查員一致確認成立。

**首腦核對註記與判定。** ⚠️ **越界發現**——這是需求文件樹，不是宿主接線。**密碼與 CM-1629 是同一把**，但「**已經被公開網站發佈**」是一個新的、性質不同的事實，所以**登記為跨 arc 總表 §3.1 新項第 84（高）**：公開文件站洩露資料庫超管密碼與兩組登入帳密。動作是**換密碼＋清 `docs/`＋重佈文件站**三件一組。決策者已於 2026-09-17 收到通報。

（本報告刻意只寫帳號名與「含密碼字串」，不記錄任何密碼明文，也不寫成帳號密碼配對。）

<a id="f4"></a>
### F4 — 代理程式下載檔案的路由，身分只靠請求標頭自己寫的一行字（中等，面板由嚴重降下，3:0）

**這是什麼問題。** 主專案自己掛了一條路由給代理程式下載檔案用。這條路上，「你是哪一台代理程式」完全來自請求標頭 `X-Agent-Uid` 裡的那個值——**由呼叫者自己填**。這個值被直接當成身分傳進下游那支「既決定給不給、又負責把檔案吐出去」的函式。

**出事會怎樣。** 下游會先用一個**繞過客戶隔離的查詢**去查「這個代理程式編號屬於哪一家客戶」，然後把整個執行環境切換成那一家客戶，再從那家客戶的資料裡找出檔案回傳出去。所以填別家客戶的代理程式編號，就會從別家客戶的資料裡拿檔案——**跨客戶成立，資料庫的隔離機制完全不會報錯**，因為連線本身就已經被切成那一家了。拿到的東西是**客戶上傳來給我們掃描的源碼壓縮包**，以及檢測設定檔。

**要先有什麼才打得到。** 連得到 `/api/1.0/agents/files/<編號>`（落地版的 nginx 用一條規則代理全部 `/api/1.0`，沒有逐路徑限制）；知道一組代理程式編號與一個該代理程式進行中工單引用的檔案編號（任何一台代理程式主機的維運人員、一台被入侵的代理程式，或任何在紀錄／派工內容裡看過這些編號的人都拿得到）；那張工單還在進行中。註解裡宣稱倚賴的用戶端憑證驗證，在出貨的 nginx 設定裡**一行都沒有**。

**在哪裡。** `api/remote_agent/routes/agent_file_route.py:49`（`AgentFileDownloadRoute.get`）。這條路由是在 `core/plugins/remote_agent.py:132` **手動裸掛**上去的，裝飾器只有 `@doc` 與 `@inject`，沒有任何守門。

**怎麼修。** 改成要求一個可驗證的憑據：平台本來就會簽短效通行證，讓代理程式帶上來，從驗過的內容推出代理程式身分，並比對它綁定的裝置指紋。如果真的打算用用戶端憑證來承載身分，那就要真的把它開起來，並把驗過的主體往後傳——**在兩者之一存在之前，這條路等於沒有身分驗證**。

**驗證。** 3/3 三位檢查員一致確認成立。**面板把嚴重度從研究員原報的嚴重降為中等**（三票為中等、嚴重、中等）。

**首腦核對註記與判定。** 屬實，**重複 CM-1595，不另計。**

這是 **R2b 的 F2／F3 已經併進 CM-1595 的那第五個裸奔端點**，本棒是**從主專案的路由這一側**看到同一件事——R2b 看的是套件那頭的授權服務，這次看的是宿主這頭「這條路由到底掛了什麼守門」。答案是：什麼都沒掛。**首腦同意面板降為中等**（與 R2b 的判定一致）。

順帶查證過依賴注入那一面：這條路由拿到的服務是用 `Factory` 註冊的（`di_containers/detection_tools/detection_orchestration_containers.py:119`），不是 Singleton，所以**沒有跨請求殘留狀態的問題**。

<a id="f5"></a>
### F5 — 同一條路由，從「根本沒有身分驗證」這一面看（中等，面板由嚴重降下，2:1）

**這是什麼問題。** 位置與 F4 是同一條路由（差一行），看的角度不同。F4 講的是「授權判斷用了不可信的輸入」，F5 講的是**更前面的一件事：這條路上根本沒有任何一道認證**。沒有守門裝飾器、沒有通行證檢查、沒有憑證檢查，掛上去的時候就是裸的。

**出事會怎樣。** 與 F4 相同：拿得到客戶的源碼壓縮包或檢測設定檔，連同它的檔名、大小與雜湊值，而且跨客戶成立。

**要先有什麼才打得到。** 與 F4 相同。研究員額外指出一點：這兩個編號**任何已登入的使用者在代理程式管理頁與檢測綁定的回應裡就看得到**，不必是攻擊者也拿得到。

**在哪裡。** `api/remote_agent/routes/agent_file_route.py:48`，裸掛點在 `core/plugins/remote_agent.py:132`。

**怎麼修。** 與 F4 同一組修法。額外一點：當代理程式認證設定是「完整」模式時，沒有驗過身分就應該直接拒絕。

**驗證。** 2/3 三位檢查員中兩位確認成立。**面板把嚴重度從研究員原報的嚴重降為中等**（兩張確認票都是中等）。

**首腦核對註記與判定。** 屬實，**與 F4 同一條路由的另一面，一併重複 CM-1595，不另計。** 同意降為中等。

<a id="f6"></a>
### F6 — 每一套安裝出來的系統，原廠管理員都是同一組密碼（中等，3:0，⚠️ 越界）

**這是什麼問題。** 安裝程式的資料庫初始化腳本裡，寫死了一組經過雜湊的原廠管理員密碼，每一套新安裝出來的系統都會被種下同一個 `admin` 帳號、同一組密碼。這個帳號是平台超級管理員，**沒有強制首次登入改密碼**，而且被保護機制擋著不能刪除或停用——客戶就算知道了也拿不掉。

**出事會怎樣。** 知道那組密碼的人（看過內部文件的離職員工、從自己那套安裝裡挖出來的客戶、或把雜湊拿去離線破解的人），可以登入**任何一家客戶**的系統當平台超級管理員，讀寫所有客戶的合規資料、證據與稽核紀錄。不需要任何客戶專屬資訊。

**要先有什麼才打得到。** 取得那組明文密碼；連得到某套部署的登入頁；密碼自安裝以來沒被改過（因為沒有強制改密，這個前提大機率成立）。

**在哪裡。** `scripts/init/06-admin.sql:41`。

**怎麼修。** 讓每套安裝各自產生一組隨機密碼（只寫進安裝紀錄、權限設 600），或乾脆不預先種這個帳號、改用既有的一次性設定精靈路徑開通。若一定要保留固定的原廠帳號，至少不要出貨一組共用的祕密。

**驗證。** 3/3 三位檢查員一致確認成立。

**首腦核對註記與判定。** ⚠️ **越界發現**——這是安裝程式的資料庫初始化腳本，不是宿主接線。**重複跨 arc 總表第 3 項**（FR-079 的 B2 F15，決策者 2026-09-09 已裁「先記錄」），**不另計**。補一個細節上去：那組雜湊會**被打進安裝用的映像檔**（`docker/init/Dockerfile:33`），而且**雜湊本身是可以拿去離線破解的**——不是只有內部人才知道。

### F7 — 被駁回

工具沒有列出這條的內容（三票一致駁回的候選不會出現在報告裡，編號的空缺就是它）。**不追。**

## 卡片重點逐項

🔴 **低強度只跑兩位研究員。卡片列的八個重點，工具實質碰到的是②（＝F4／F5）與⑤（＝F2）。其餘六項由首腦回頭開檔人工查證，六項全部乾淨。**

### ① 管理端點的守門殼是不是真的三層都在（**工具未報，人工查證**）

**結論：乾淨。**

`core/plugins/remote_agent.py:14-16` 傳給套件的那個守門函式，實際上是三層疊起來的：先確認你登入了（`jwt_required()`）→ 再確認這套系統的授權有買這個功能（`require_license("remote-agent-manage")`）→ 最後確認你這個人有這個權限（`require_capability("remote-agent-manage.create")`）。

三件事都查過：

- **順序正確**——先驗登入才查授權，不會出現「還沒證明你是誰就先去查你有沒有權限」這種倒因為果。
- **缺授權時是關門不是開門**——`common/authz/license.py:286-310` 的 `require_license` 在查不到授權時是直接丟拒絕錯誤（`ForbiddenError`），不是靜靜放行。這叫「出錯就關門」，是對的那一種。
- **不漏掛**——套件那側的 `_guard` 只包五種 HTTP 方法，但本套件的資源類別沒有第六種方法，不漏。

另外，有幾個唯讀的端點也吃了 `.create` 這個權限點，程式碼註解自陳「這是刻意收緊、不是寫錯」——查證屬實，**收緊不是放寬，不成問題**。

### ② 代理程式下載檔案那條路由的守門（**工具已報＝F4／F5**）

**結論：成立。** 詳見上方兩條。這是本棒唯一被工具吃透的一項。

### ③ 代理程式認證的總開關預設是什麼（**工具未報，人工查證**）

**結論：與 R2b 的結論一致，不另計。**

程式碼裡的預設值是「不驗」（`config/config.py:257` 與 `common/util/agent_auth_settings.py:22` 都是 `none`）。安裝程式那側：**全新安裝會強制設成「完整」**（`install.sh:1657`），**升級則保留機器上既有的值**（`:1645`）。

這代表 R2b 已經記過的那件事依然成立：**舊機器如果當初停在「不驗」，升級不會幫它改過來**。這條在 R2b 已經登記，本棒不重複計。

### ④ 資料面 adapter 有沒有被拿來當跳板（**工具未報，人工查證**）

**結論：乾淨，另記一筆非資安小坑。**

雲端主動打回客戶機房代理程式的時候，那層轉接程式會組出一個「動作字串」丟進稽核紀錄，形式是 `方法 路徑`。查過那個路徑的來源（`:110`／`:136`／`:151`）——是 `/blob/<系統產生的檔案編號>`，**那個編號是系統產的代理程式識別碼，不是使用者可以自己取的檔名**，所以沒有注入的空間。

要打哪一台是用工單記錄的位址反查出來的（`_route_for_entity`，`:169`）。這個位址可以被租戶管理員在管理頁上改掉——**但那正是 R1 的 F6 已經記過的接管路徑（CM-1597）**，不是本棒的新發現。

憑證與通行證都不會被寫進系統紀錄（把 16 檔的紀錄呼叫全 grep 過一遍，零命中）。

**非資安小坑一筆**：驗證回應指紋的那支函式，在「預期指紋是空的」時候會直接放行。這只會發生在**裝置指紋欄位是空的舊資料列**上。記在這裡備查，不升為發現。

### ⑤ 掃描工單裡的明文帳密是在哪裡生出來的（**工具已報＝F2**）

**結論：成立，而且這一棒補上了「宿主側的終點」這塊拼圖。** 詳見 F2。

### ⑥ 依賴注入有沒有跨請求殘留狀態（**工具未報，人工查證**）

**結論：乾淨。**

三支 repository 都查過：`RemoteAgentRepoImpl` 與 `AgentTaskRepoImpl` 繼承 `BaseRepositoryImpl`（連線是延後取得的屬性），`RemoteAgentReconQuery` 自己寫了同樣形式的延後屬性（`recon_query_adapter.py:18-20`）。這三支雖然註冊成單例，**但身上沒有任何屬於單次請求的狀態**，不會把 A 請求的東西留給 B 請求。

### ⑦ 對帳查詢有沒有客戶隔離（**工具未報，人工查證**）

**結論：不成立。**

那支對帳查詢用「上傳檔案的位址等於代理程式位址」來配對，查詢本身**沒有帶客戶條件**，靠資料庫的隔離機制擋。原本擔心的是兩家客戶剛好用同一個內網位址時會互看到。

**但 `upload_files` 這張表已經在 2026-09-16 補上隔離機制了（跨 arc 總表第 47 項已修）**，所以這條現在被資料庫擋住——兩家客戶即使位址一樣，各自也只看得到自己那幾列。**不成立。**

### ⑧ 宿主接線有沒有自己開後門（**工具未報，人工查證**）

**結論：乾淨。**

16 檔裡 grep 三個「繞過隔離」「系統身分」「是超級管理員」相關的關鍵字，**零命中**——主專案這層接線沒有自己開任何提權捷徑。

另外查了三個延遲載入的代理物件：它們解析不到目標時是**直接拋錯**，不是回一個空值然後讓後面的程式當作「沒設定就放行」。這叫「出錯就大聲」，是對的那一種。

## 這份結果可信到什麼程度

分兩層看。

**「這六條是真的嗎」→ 可信。** 21 票全數投出、除 F5 之外全部 3:0 一致通過、驗證章蓋 `verified`、沒有任何候選被退件或延到下一輪（唯一被駁回的 F7 是三票一致駁回）。首腦逐條開檔核對過行號。其中 F3 那條**首腦親自打開公開網址確認頁面真的在線上、真的含密碼字串**——這是本 arc 唯一一條有「實際打開看到」而非只靠讀程式碼的發現。F2 更是**第四次獨立確認**。

**「只有這六條嗎」→ 中等偏高。** 好的一面：兩位研究員都完整回報、面板完整跑完、驗證章通過；卡片列的八個重點工具碰到兩個，**其餘六個首腦人工補查全部乾淨**——不是「沒查」而是「查了沒事」。不能宣稱完整的一面：低強度跑法沒有元件盤點、沒有威脅建模、工具沒留逐檔紀錄（`coverage.research` 是 `null`），而且掃描當下工作區有別條線的未提交改動（驗證章標 `-dirty`），那些改動不在 16 檔範圍內、不影響本棒結論，但嚴格說起來掃的不是一個乾淨的樹。

**範圍內淨新增 0，越界撈到 1 條升級事實。** 六條裡三條併 CM-1595（F2／F4／F5）、一條併 CM-1629（F1）、一條併總表第 3 項（F6），**只有 F3 產生總表新項第 84**——而它新的不是「找到一個沒人知道的洞」，是「已知的洞原來比想像中開得更大」。

## 執行概況

| 項目 | 數字 |
|---|---|
| 檢查範圍 | 16 個受版控 Python 檔（主專案把遠端代理程式套件接上來的那一層：管理端點守門、檔案下載路由、認證設定、資料面 adapter、任務付載提供器、對帳查詢、兩個依賴注入容器） |
| 檢查強度 | 最低（`low`），focus 設在攻擊面 |
| 候選問題 → 去除重複 | 8 → 7 |
| 投票數 | 21（7 條候選 × 3 位檢查員），全數投出，沒有漏投、沒有中斷、沒有被延到下一輪 |
| 通過 / 駁回 | 通過 6（F1／F2／F3／F4／F6 為 3:0，F5 為 2:1）；駁回 1（F7，3:0 一致駁回，工具未列內容） |
| 被降低嚴重度的 | 2（F4 與 F5：研究員報嚴重 → 面板定中等；F4 三票為中等／嚴重／中等，F5 兩張確認票皆中等） |
| 研究員派出 / 回收 | 2 / 2 |
| 驗證章狀態 | **`verified`** |
| 掃描耗時 | 6,055 秒（約 1 小時 41 分） |
| 掃描當下的程式碼版本 | commit `4bf687c0`，branch `feature/review`，**工作區有未提交改動（驗證章標 `-dirty`）**——那些改動屬於別條線、不在本棒 16 檔內；16 檔自 `4bf687c0` 到現在的 HEAD 零漂移 |
| 首腦人工補查項目 | 卡片八個重點中的①（守門殼三層）、③（認證總開關預設）、④（資料面 adapter）、⑥（依賴注入殘留狀態）、⑦（對帳查詢隔離）、⑧（自開後門），六項全部乾淨 |
| 對總表的影響 | §1 加 R3 一列；**範圍內淨新增 0**；§3.1 加新項第 84（HIGH，公開文件站洩密）；CM-1629 補「腳本類落點」；總表第 3 項補「雜湊已打進安裝映像檔」；§3.2 候選（指紋為空時放行）暫不登記 |

## 交付狀況

🔴 **本棒 runner 四件全未交**：沒有寫報告、沒有 commit、沒有回寫 Notion（CM-1594 仍停在「未開始」）、沒有回報。工具產物是首腦自己到掃描目錄撈出來的，六條發現的逐條開檔核對、卡片八個重點裡六項的人工查證、F3 公開網址的實際 fetch 驗證，也全部由首腦完成。**本報告由首腦補寫，這是全計畫第十一次 runner 交付掛零。**

---

原始工具產出：`~/Projects/Billows/Audit-Manager/compliance-manager-be/CLAUDE-SECURITY-20260917-015011/`
（`CLAUDE-SECURITY-RESULTS.md` 為工具原文，本報告為首腦整理版，含逐項人工查證。）
