---
title: FR-195 Agent 資安修正
status: ✅ 可派的 14 張全部做完並通過首腦實質驗收，2026-11-12 已合回主線 feature/FR-172 並推上遠端；CM-3833、CM-3834 決策者裁示先不做
lede: "把 FR-186（Agent 本體資安掃描第二輪）掃出來的 1 高 14 中 15 低修掉。主要在 Agent repo，另有一張前端配合卡與一張 jedi-ldap 套件卡。"
notion:
  parent: {id: CM-3822, title: "FR-195 Agent 資安修正：FR-186 掃描的 1 高 14 中 15 低", url: "https://app.notion.com/p/FR-194-Agent-FR-186-1-14-15-14-3-414346da4cd0817fafabf1e822bd80f0"}
  children:
    - {id: CM-3823, title: "F1 升級驗章：程式樹裡有捷徑檔、特殊檔或清單外的檔一律拒收（Python 這一半）", url: "https://app.notion.com/p/FR-194-F1-Python-414346da4cd08158a9a5cdc6aca057a9", status: Not started}
    - {id: CM-3824, title: "F2 改本機對外位址只准本機管理員，並要再輸一次本機管理員密碼", url: "https://app.notion.com/p/FR-194-F2-414346da4cd0816aa338f9919249087a", status: Not started}
    - {id: CM-3825, title: "F2-FE 主控台「改本機對外位址」對話框：只給本機管理員、加本機管理員密碼欄", url: "https://app.notion.com/p/FR-194-F2-FE-414346da4cd081afb905e1b59ae09cf4", status: Not started}
    - {id: CM-3826, title: "F3 工具伺服器位址連線前先過授權清冊（測試連線、手動掃描、派工三個入口）", url: "https://app.notion.com/p/FR-194-F3-414346da4cd081348342dffb160f54fc", status: Not started}
    - {id: CM-3827, title: "F4 工具設定：改 SSH／WinRM 連接埠、HTTPS 開關、CA 憑證也要重填已存的祕密", url: "https://app.notion.com/p/FR-194-F4-SSH-WinRM-HTTPS-CA-414346da4cd081d08407dcaaf2b44840", status: Not started}
    - {id: CM-3828, title: "F5 LDAP「測試連線」只准本機管理員", url: "https://app.notion.com/p/FR-194-F5-LDAP-414346da4cd081d48564fc2f7afc8d45", status: Not started}
    - {id: CM-3829, title: "F6 SonarQube 接頭：位址非本機只收 https、源碼包不能夾帶設定檔、clone 不跟轉址、子行程只帶必要環境變數", url: "https://app.notion.com/p/FR-194-F6-SonarQube-https-clone-414346da4cd0818ca018e95aa1a17532", status: Not started}
    - {id: CM-3830, title: "F7 吃光記憶體三處：tar 擴充標頭、nmap 遠端報告、SSH 指令輸出，都在讀進記憶體前設上限", url: "https://app.notion.com/p/FR-194-F7-tar-nmap-SSH-414346da4cd081f8a7d6cc1a3d350fa2", status: Not started}
    - {id: CM-3831, title: "F8 本機檔案權限：資料目錄只有擁有者可進、PDF 暫存移出公共 /tmp、原生安裝的服務設檔案權限遮罩", url: "https://app.notion.com/p/FR-194-F8-PDF-tmp-414346da4cd081c29c59d9fae307fa20", status: Not started}
    - {id: CM-3832, title: "F9 低風險五項：改密碼不重置 session 起算時間、改狀態的主控台請求只收 JSON、登入 log 擋換行、錯誤回報不帶區域變數、漏洞庫清單壞掉不當成首次安裝", url: "https://app.notion.com/p/FR-194-F9-session-JSON-log-CA-414346da4cd081d697ccdda6d9478b52", status: Not started}
    - {id: CM-3833, title: "F10 升級驗章主機端那一半：存主機副本時直接用驗過的那份樹，不再從映像取第二次", url: "https://app.notion.com/p/FR-194-F10-FR-193-414346da4cd08114934ccbe77e9519ef", status: 暫緩}
    - {id: CM-3834, title: "F11 安裝腳本三項：TPM 工具雜湊清單要驗章、儲存密鑰不上命令列、出廠儲存快照加密存放", url: "https://app.notion.com/p/FR-194-F11-FR-193-TPM-414346da4cd081069d3dd34703bd6ce6", status: 暫緩}
    - {id: CM-3835, title: "F12 連 Windows 主機（WinRM）：開了 HTTPS 的第一次連線記住對方憑證指紋，之後不符就拒絕", url: "https://app.notion.com/p/FR-194-F12-WinRM-Windows-414346da4cd081c78de0d8339f00e914", status: Not started}
    - {id: CM-3836, title: "F13 jedi-ldap：OpenLDAP 登入時目錄裡找到超過一筆同名的就拒絕，不再拿第一筆", url: "https://app.notion.com/p/FR-194-F13-OpenLDAP-414346da4cd081039a16e0ecc29baadf", status: Not started}
    - {id: CM-3871, title: "G1 解壓縮上限算得偏緊：長路徑的合法壓縮包會被誤擋，每個檔的餘裕從 1 KB 調到 8 KB", url: "https://app.notion.com/p/FR-195-G1-1-KB-8-KB-415346da4cd081cda778e358c9be649a", status: Not started}
    - {id: CM-3872, title: "G2 漏洞庫清單讀不到時不再永久停止更新：改用現行資料的目錄名當日期，降版檢查照樣有效", url: "https://app.notion.com/p/FR-195-G2-415346da4cd0818d81f9f79122343698", status: Not started}
relates: [FR-186, FR-177, FR-193, FR-188, FR-190]
---

# FR-195 Agent 資安修正

> 掃描在 [FR-186](../FR-186-2611-agent-security-rescan/README.md)（母卡 CM-3675，35 棒全部驗收完）；逐棒報告正本在 Agent repo `docs/security-scan/FR-186/scan-*.md`。跨 arc 的結論與覆蓋率在 [`security-scan-consolidated/`](../security-scan-consolidated/index.html)。

## 這案在做什麼

FR-186 把 Agent 整包重掃一次，結果是 1 條高風險、14 條中、15 條低。本案把它們修掉，同一支檔、同一個原因的併成一張卡。

卡上的行號對 Agent 主線 `b8b1158`（FR-188、FR-190、FR-193 rootless 已合回）核過。1 高與 14 中首腦逐條開檔核過，全部仍然成立。F2～F6 的修法在暫存工作區各試做過一次並跑全量測試，每張卡會讓哪些既有測試變紅、為什麼、怎麼改，都寫在卡上。全量測試基準 2554 passed。

## 關鍵決策

- **卡上不留要人決定的事**。工作坊是半夜無人值守跑的；遇到取捨，首腦先查產品裡別處怎麼做、哪個選項不改變既有客戶的用法，自己定案寫進卡。
- **唯一的高風險先修入口**：升級驗章「跟著捷徑檔走」這條，先在 Python 端擋掉捷徑檔與清單外的檔（F1），攻擊的入口就封住了。正式出貨的 1.7.4 映像實查過：程式樹 270 個檔、0 個捷徑檔，清單外只有 `manifest.json` 與 `manifest.sig`，新規則不會擋到正版升級。
- **主機腳本那一半（F10）範圍已縮小**：FR-193 合回後，升級腳本改成「驗過章才存一份主機副本、之後都執行主機副本」。剩下的洞只有一處——驗完把驗過的樹刪掉，存副本時又從映像取第二次；F10 要改成直接用驗過的那份。
- **工具伺服器位址也要在授權清冊內**（F3）；本機迴路位址例外，因為那條線出不了這台機器。客戶的 SonarQube／OpenVAS 伺服器要先在主系統登記成設備。
- **改設定要重填密碼只補確定會換連線對象的欄位**（F4：SSH／WinRM 連接埠、HTTPS 開關、CA 憑證）；只改帳號名稱不用重填，這是既有的刻意行為，不推翻。
- **連 Windows 主機比照 SSH：第一次連線記住對方憑證指紋**（F12）。客戶不用匯入任何憑證，跟遠端桌面第一次連線問要不要信任是同一種做法；Agent 出貨的檢測工具本身支援釘指紋（`train-winrm` 的 `ssl_peer_fingerprint`）。沒開 HTTPS 的主機沒有憑證可記，照舊能掃、只多一句提示，預設值不動。
- **OpenLDAP 找到多筆同名就拒絕**（F13）。改在 jedi-ldap 套件，主系統與 Agent 登入共用；客戶的登入帳號不用變。

## 📊 總進度

| 批 | 卡 | repo | 做什麼 | 嚴重度 | 來源（FR-186 的棒與條） | 狀態 |
|---|---|---|---|---|---|---|
| 1 | CM-3823 F1 | agent | 升級驗章：程式樹裡有捷徑檔、特殊檔或清單外的檔一律拒收（Python 這一半） | 高 | S7 F1（3/3 票）＋舊觀察 O1 | 驗收通過 |
| 1 | CM-3826 F3 | agent | 工具伺服器位址連線前先過授權清冊（測試連線、手動掃描、派工三個入口） | 中 | X2 F1、K2 F2（皆 3/3 票）；C4 F2 同條 | 驗收通過 |
| 1 | CM-3827 F4 | agent | 工具設定：改 SSH／WinRM 連接埠、HTTPS 開關、CA 憑證也要重填已存的祕密 | 中 | X1 F1、C5 F1、C5 F2（皆 3/3 票） | 驗收通過 |
| 1 | CM-3828 F5 | agent | LDAP「測試連線」只准本機管理員 | 中 | I2 F1（3/3 票） | 驗收通過 |
| 1 | CM-3829 F6 | agent | SonarQube 接頭：位址非本機只收 https、源碼包不能夾帶設定檔、clone 不跟轉址、子行程只帶必要環境變數 | 中 | C1 F1（3/3 票）＋人工 M1、M2、M3；S8 F1（3/3 票） | 驗收通過 |
| 1 | CM-3831 F8 | agent | 本機檔案權限：資料目錄只有擁有者可進、PDF 暫存移出公共 /tmp、原生安裝的服務設檔案權限遮罩 | 中 | P3 F1、P3 F2、H5 F1（皆 3/3 票） | 驗收通過 |
| 1 | CM-3836 F13 | jedi-packages | jedi-ldap：OpenLDAP 登入時目錄裡找到超過一筆同名的就拒絕，不再拿第一筆 | 中 | I2 F2（3/3 票） | 驗收通過 |
| 2 | CM-3824 F2 | agent | 改本機對外位址只准本機管理員，並要再輸一次本機管理員密碼 | 中 | S1a F1（3/3 票）；K2 F1 同一條 | 驗收通過 |
| 2 | CM-3825 F2-FE | fe | 主控台「改本機對外位址」對話框：只給本機管理員、加本機管理員密碼欄 | 中 | 配合 F2（S1a F1） | 驗收通過 |
| 2 | CM-3830 F7 | agent | 吃光記憶體三處：tar 擴充標頭、nmap 遠端報告、SSH 指令輸出，都在讀進記憶體前設上限 | 中 | S6 F1（3/3 票，FR-177 #226 修法的旁路）、C3 F1、C6 F1（皆 3/3 票） | 驗收通過（補卡 CM-3871） |
| 2 | CM-3832 F9 | agent | 低風險五項：改密碼不重置 session 起算時間、改狀態的主控台請求只收 JSON、登入 log 擋換行、錯誤回報不帶區域變數、漏洞庫清單壞掉不當成首次安裝 | 低 | I1 F1（2/3 票）、I1 F2、I1 F4（3/3 票）、P1 F1（3/3 票）、S7 舊觀察 O2 | 驗收通過（補卡 CM-3872） |
| 2 | CM-3835 F12 | agent | 連 Windows 主機（WinRM）：開了 HTTPS 的第一次連線記住對方憑證指紋，之後不符就拒絕 | 中 | C2 F1（3/3 票） | 驗收通過 |
| 3 | CM-3833 F10 | agent | 升級驗章主機端那一半：存主機副本時直接用驗過的那份樹，不再從映像取第二次 | 高（第二層防線） | S7 F1 的主機端修法；H4 第 6 節列的受影響位置 | 暫緩（決策者 2026-11-12 裁示先不做） |
| 3 | CM-3834 F11 | agent | 安裝腳本三項：TPM 工具雜湊清單要驗章、儲存密鑰不上命令列、出廠儲存快照加密存放 | 中 | H3 F1、H1 F1（皆 3/3 票）、H2 M1（人工） | 暫緩（決策者 2026-11-12 裁示先不做） |
| 4 | CM-3871 G1 | agent | 解壓縮上限算得偏緊：長路徑的合法壓縮包會被誤擋，每個檔的餘裕從 1 KB 調到 8 KB | 修正前一張卡的副作用 | 首腦驗收 F7（CM-3830）時實測發現 | 驗收通過 |
| 4 | CM-3872 G2 | agent | 漏洞庫清單讀不到時不再永久停止更新：改用現行資料的目錄名當日期，降版檢查照樣有效 | 修正前一張卡的副作用 | 首腦驗收 F9（CM-3832）F 項時發現 | 驗收通過 |

批＝工作坊同時開的那一組。同一批的卡不改同一支檔（含測試檔、體積白名單、資安規則檔），腳本比對過同批衝突為 0。

暫緩的 2 張決策者裁示先不做。它們現在沒有東西擋著（原本以為要等的 FR-193 CM-3810、CM-3811 卡上寫明不用做、內容已併入 CM-3809），但卡的內文還是舊的，重開前要對最新的安裝腳本重寫。

## 首腦實質驗收（2026-11-11）

可派的 14 張全部跑完，沒有一張卡住或退回。首腦逐張讀 diff，並在三個 repo 合起來的結果上重跑測試。

- **Agent（12 張，含兩張補卡）**：工作坊 branch `ws-CM-3822`（`9ac649e`，已跟上主線 1.7.6）全量 2586 passed、1 skipped、0 failed；守衛 109 passed。53 個檔、+853／-129。沒有動到安裝與升級腳本；體積白名單兩個數字都是往下調。
- **前端（1 張）、jedi-ldap（1 張）**：讀過 diff 通過；jedi-ldap 測試 40 passed。
- **已合回主線**（2026-11-12，決策者指示先合回一版）：Agent `b011adc`（合回前主線是 1.7.7）、前端 `5e017f1b`、jedi-packages `ebf43bd3`，三個 repo 都已推上遠端。合回後在 Agent 主線上重跑全量 2586 passed、守衛 109 passed；jedi-ldap 40 passed。尚未隨版本出貨給客戶。

**驗收時發現兩個副作用，各開一張補卡，兩張都已做完並通過驗收**（都是開卡時沒想到的，不是小弟沒照卡做）：

| 原卡 | 副作用 | 補卡 |
|---|---|---|
| CM-3830 F7 | 解壓縮的總量上限給每個檔 1 KB 的餘裕，只夠短檔名；路徑超過約 155 字的檔 tar 會多佔 2 KB 以上，長路徑檔很多、總量又貼近上限的合法壓縮包會被誤擋 | CM-3871 G1：餘裕調到 8 KB |
| CM-3832 F9 | 漏洞庫清單檔只要讀不到一次，這台 Agent 的漏洞庫就永久停止更新，手動「立即檢查更新」也救不回來 | CM-3872 G2：清單讀不到時改用現行資料的目錄名當日期 |

**多查、結果沒問題的四件事**：升級驗章的新規則不會擋到正版（1.5.6／1.6.0／1.7.2／1.7.4／1.7.5 五個版本的程式樹都是 0 個捷徑檔，並用 1.7.5 正式產物照新規則逐項檢查）；工具位址檢查實測 16 種寫法找不到繞過；PDF 暫存搬到資料目錄下不會讓轉檔壞掉（套件用的是可跨裝置的搬移）；WinRM 給了指紋後自簽憑證照樣能用（讀了出貨工具 `chef-winrm 2.5.0` 的實作）。

**還沒驗到、要真機的三件事**：對真的 SonarQube 伺服器跑一次 scan 模式（F6）；原生安裝的機器實際升級一次看資料目錄權限（F8）；對開了 WinRM HTTPS 的 Windows 主機掃一次（F12）。

## 客戶會感覺到的行為變更

- **F3**：SonarQube／ZAP／OpenVAS 的伺服器位址不是本機、也不在主系統設備清冊內的，測試連線與掃描會被擋。
- **F4**：改工具的連接埠、HTTPS 開關或 CA 憑證時，要把密碼重填一次。
- **F6**：SonarQube 伺服器位址非本機只收 https。
- **F12**：開了 WinRM HTTPS 的 Windows 主機，換憑證或重灌後掃描會被拒，要清掉舊指紋。
- **F13**：OpenLDAP 目錄裡有重名條目的帳號會登入失敗。

## 收尾待辦（全部做完後）

- jedi-ldap 0.1.1 發版，Agent 與主系統重裝後 F13 才生效。
- 手冊補四段：工具伺服器要先登記成設備（F3）、改連接埠或 CA 要重填密碼（F4）、SonarQube 只收 https（F6）、Windows 主機換憑證後怎麼清掉舊指紋（F12）。
- F12 對一台開了 WinRM HTTPS 的 Windows 主機實際掃一次，確認指紋被記下。
- F10、F11 先不做（決策者 2026-11-12）。重開前要知道的三件事：F11「儲存密鑰上命令列」不能改用 openssl 從檔案讀金鑰——實測 Ubuntu 22.04／24.04、Debian 12、Rocky 9 的 openssl 都不支援，而且五輪簽章的金鑰都在命令列上；F11「TPM 工具清單沒簽章」實際是容器版交付包首次安裝時整份完整性清單都沒有原廠簽章驗證，屬出版流程的題目，要另開案；F10 在 rootless 之後的風險是映像庫屬 `guidant` 帳號、升級腳本由 root 執行，驗完到存主機副本之間映像可被換掉。
- ZAP、OpenVAS 目前要客戶自己貼 CA 憑證，這個設計不對（決策者 2026-11-11 指出）；要比照 SSH、LDAP、WinRM 改成第一次連線記住對方指紋。本案不做，另開卡；F9 裡「貼了自訂 CA 只信那一張」那一項因此不修。
- 修完的項目登回跨 arc 總表；FR-186 的逐棒進度表與母卡結案。

## 驗收

每張卡首腦讀 diff＋跑卡上列的測試；合回前在暫存區把最新主線與這批預合跑過全量與守衛，合回後在主線上再跑一次，皆通過。
