FR-177 總結報告(PM 版):Guidant AI Agent 本體資安掃描

FR-177 總結報告:Guidant AI Agent 本體資安掃描

掃描時間 2026-11-05 23:30 ~ 11-06 05:00,25 棒全部完成。掃描對象:Agent repo evidence-agent 釘 commit bab2aa3(第二、三期因報告合回而落在 3813abd/749d3b4/63334f4,程式碼與 bab2aa3 相同)。工具:Claude Code 官方 claude-security plugin 0.12.0,每棒一位研究員讀全範圍、三位獨立檢查員對每條候選投票。首腦對每條通過的發現都開檔核對過行號與呼叫路徑;高風險那條四段逐行核對攻擊路徑。

這是 PM 版:講有什麼問題、多嚴重、為什麼、怎麼修的方向、先修哪些。不含程式檔名與行號(漏洞還沒修,位置不公開)。要看每條的確切位置與函式級修法,請看 Agent repo 內的工程師版 docs/security-scan/FR-177/SUMMARY-engineering.md。跨六輪掃描的累積總表在 security-scan-consolidated/。


🔴 結論:要修 1 件急的、12 件中等的,修法方向已定

Agent 是我們裝在客戶自己機器上的程式。前六輪資安掃描(2026-09,140 輪)掃的全是主系統與套件,Agent 本體一個檔都沒掃過;這一次補上。

數量 一句話
高 1 主控台「手動掃描」可以手填任意檢測規則包的路徑,Agent 原樣拿去執行,等於有「發動本機掃描」權限的人能在 Agent 主機上跑任意程式(#223)
中 12 8443 埠開一條空連線就能凍住 Agent、做壞的壓縮檔吃光記憶體、LDAP 來源可改成假伺服器冒充他人、登入入口不限大小、改工具位址會把舊密碼送到新位址、Agent 被拿來連清冊外主機(兩種路)、手動升級路徑以 root 跑未驗章的腳本、三支掃描工具接頭連線不驗對方身分(InSpec SSH 不驗主機指紋、連 ZAP 走明文、連 OpenVAS 不驗憑證)、私鑰建檔瞬間權限太寬
低 9 登入狀態該踢沒踢的三種情況、診斷包權限、總覽帶出掃描目標、ZAP 爬蟲範圍封口、DNS 探測可被卡死、代理帳密沒遮

核實乾淨的部分,每一塊至少兩棒從不同角度看過:自動更新鏈(下載→驗指紋→用現行版驗新版原廠簽章→擋降版,新版程式在驗章前一行都沒執行)、Ed25519 簽章核心與啟動完整性閘、8443 的身分驗證守門殼、Agent 對外連線的 TLS 驗證沒有任何關閉的路、瀏覽器直傳的一次性票券、本機登入的密碼雜湊與鎖定、祕密保管的加密。

這一輪的方法論結果:25 棒全部面板完整跑完、無一棒中斷、runner 無一棒缺交。這是六輪掃描以來第一次,原因是每棒壓在 1,000 行上下、且用工作坊的開場 prompt 自動啟動。


§1

一、掃了什麼、怎麼切

Agent 本體 237 支 Python、約 27,400 行,加 3 支主機端升級腳本(bash)。按「客戶內網直接打得到的入口」優先,分三期:

期 棒 涵蓋 檔/行
第一期(8 棒) A1~A8 註冊與憑證、8443 收指令、線上更新鏈、規則包解壓、簽章核心與啟動閘、主控台本機登入、LDAP 與網段白名單、證據檔直傳 63/8,500
第二期(9 棒) B1~B8 主控台全部路由與聚合層、掃描任務執行與工具帳密、執行紀錄與上傳槽、目標清冊與回報、主系統通道與設定拉取、祕密保管與診斷包與裝置指紋、主機端升級腳本 71/9,300
第三期(8 棒) C1~C8 各掃描工具的接頭(SonarQube、InSpec、Nmap、ZAP、OpenSCAP、OpenVAS、SBOM)與網路診斷十項探測——全部是 Agent 組參數去跑外部工具或連客戶主機的地方 33/8,300

沒掃、首腦用 grep 補查的:設定檔、依賴注入接線、錯誤碼表、各 port 介面、migration。

每棒的 scope 寫死在 Notion 卡上,研究員越界讀到的東西驗收時挑掉。


§2

二、找到什麼:按嚴重度列

嚴重度判準:高=不需要特殊前提就能拿到不該拿的控制權或資料;中=要先有某個前提(已登入、特定權限、在內網特定位置);低=只能讓已經在裡面的人多留一會、或多看到一點。每條的「出處」指向逐棒報告與跨 arc 總表的項次。

🔴 高(1 條)

#223 主控台手動掃描可手填任意 InSpec 規則包,Agent 原樣執行

  • 這是什麼問題:主控台「手動掃描」頁選 CINC Auditor/InSpec 工具時,profile 欄位可以填任何路徑或網址。這個值一路傳到執行點都沒有人擋,Agent 就用它跑 cinc-auditor exec <你填的東西>。規則包本質是 Ruby 程式碼。
  • 出事會怎樣:填一個攻擊者自己寫的規則包網址,Agent 主機就執行了攻擊者的程式。Agent 主機上存著客戶所有掃描工具的帳密(SonarQube token、SSH/WinRM 帳密)、Agent 自己的私鑰、本機資料庫,全部讀得走。
  • 要先有什麼才打得到:主控台帳號有「發動本機掃描」權限、Agent 設好了 InSpec 帳密、目標清冊至少有一台主機。任何正常使用中的 Agent 都滿足。
  • 在哪裡:主控台路由層 → 本機掃描排程 → InSpec 接頭,四段都沒有擋,首腦逐行核對過。
  • 怎麼修:手動掃描只准選「主系統同步下來的規則包」,手填路徑一律拒收;同時把主控台的參數過濾改成「每個工具列舉可以收哪些欄位」,而不是現在的「只擋底線開頭」。
  • 出處:B5 F1(3:0)、B2 M1(3:0)、C2 F1 再確認。

中(12 條)

# 這是什麼問題(白話) 出事會怎樣 要先有什麼 在哪裡 出處
225 對 Agent 8443 埠開一條 TCP 連線、不完成 TLS 握手,Agent 就卡住 主系統派工、重啟、升級、取檔全部停擺,直到連線斷或重啟服務;不洩資料 能連到 8443(客戶內網任何機器) werkzeug 在接連線那條執行緒做握手且無逾時 A2 F1(3:0)
226 解 tar 壓縮檔時先把所有成員讀進記憶體數檔案,才查配額 一個做壞的小壓縮檔讓 Agent 整支當掉;更新包、漏洞庫、規則包、源碼包四條路都走這裡 能讓 Agent 解一個壓縮檔(主控台有掃描或更新權限) — A4 F1(3:0)
227 只要有「設定」權限就能把 LDAP 來源改成自己架的假伺服器 冒充名單上權限更大的操作者登入,別人用 AD 登入時密碼也被收走 已有 configure 權限、名單上有權限比他大的人 兩支 PUT 都只要 configure A7 F1(3:0)
229 主控台登入入口收請求內容沒有大小上限 不用登入就能送幾 GB 把 Agent 記憶體吃光 來源在 8444 允許網段內 用 整包讀,沒掛 B1 F1(3:0)、B3 人工
232 主控台改掃描工具的「位址」時,密碼欄留空就沿用舊密碼 有 configure 的人把位址改成自己的機器、按「測試連線」,客戶的 SonarQube token/OpenVAS 密碼就送過去了。我們自己的資安需求 SR-06.3 寫「位址改了祕密要重填」,LDAP 那頁有做、這頁沒做 configure 權限、該工具已存過帳密 沒傳 , 的 永遠 False B4 F1(3:0)
224 SonarQube 的 repo_url 不經過「Agent 准連哪些主機」的清冊檢查 Agent 被當跳板對內網任意主機 git clone,錯誤訊息回給使用者可探測內網 有本機掃描權限、設好 SonarQube 清冊只比對固定鍵名 B5 F2、B2 M2、B6a F1、C1 F1(皆 3:0)
233 清冊比對網址目標時查一次 DNS,掃描工具連線時又自己查一次,兩次可以拿到不同 IP(DNS 換綁) ZAP 主動掃描(會送攻擊流量)打到清冊外的內網主機 能發動 ZAP 掃描、掌控一個網域 解出的 IP 不綁給工具 B6a F2、C4 F2(3:0)
234 用交付包手動升級 Agent 時,主機以 root 從新映像裡取出升級腳本直接執行,前面只比對包內自帶的指紋、沒驗原廠簽章 拿到偽造交付包的維運人員一執行,偽包的程式就以 root 跑在客戶主機上。自動升級那條路沒這問題:它先用現行版驗新版簽章才交棒(B8 逐行核時序) 維運人員拿到並親手執行一個被換掉的交付包 — B7 F1(3:0)、B8 觀察 1
C2-F2 InSpec 用 SSH 連 Linux 目標主機時不檢查對方的主機指紋(SSH 用來確認「連到的真的是那台機器」的身分證) 內網裡冒充目標主機 IP 的人拿到稽核帳號的密碼,或回傳假的檢測結果。同一套程式裡 OpenSCAP 與 Nmap 兩個接頭都有做這個檢查,只有 InSpec 漏了 攻擊者在客戶內網、能搶到目標主機的 IP 無任何指紋欄位; 只被 openscap、nmap 引用 C2 F2(3:0)
238 Agent 連客戶的 OpenVAS 弱點掃描器時不驗 TLS 憑證 同網段做中間人的人拿走 OpenVAS 帳密,或回一份假的弱點報告讓 Agent 當證據上傳 能在 Agent 與 OpenVAS 之間做中間人 不帶 ,python-gvm 預設不驗 C5 F1(3:0)
C4-F1 Agent 連 ZAP 掃描器預設走明文 http;就算設 https,ZAP 官方 Python 套件寫死不驗憑證 在 Agent 與 ZAP 之間偷聽的人拿到 ZAP 的 API key(等於整台 ZAP 的遙控器)與登入後掃描用的目標網站帳密 能在 Agent 與 ZAP 之間的網路偷聽 沒 scheme 時補 、、 帳密送出處 C4 F1(3:0)
219 Agent 註冊時私鑰與通行證檔「先建檔、寫完、再改權限」,建檔那一瞬間用系統預設權限(常是大家可讀);改權限失敗時默默放過 同台機器上有普通帳號的人在那一瞬間讀到私鑰,就能冒充這台 Agent 已在客戶機器上有帳號且憑證目錄可進 、 A1 人工 M1(未經面板,首腦核對屬實);判低~中

低(9 條)

# 這是什麼問題 位置 出處
220 主控台登入狀態只要一直在用就永遠不過期,主系統停權後 Agent 不會跟著踢 — A6 F1(3:0)
221 在主控台改密碼,不會把同一帳號其他已登入的狀態作廢(命令列重設那條會) — A6 F2(3:0)
222 AD 帳號登入失敗時,名單上的人回應比較慢,量時間就能篩出哪些 AD 帳號能登入 — A6 F3(3:0)
228 主系統縮減某人權限(人還在名單上)時,他正在用的登入狀態不會被踢 — A7 F2(3:0)
230 下載診斷包只要「設定」權限,沒要求「下載檔案」權限 — B1 F2(2:1)
231 總覽頁「正在執行」清單不看權限,一律帶出掃描目標 IP 與設備名 — B3 F1(3:0)
C4-F3 ZAP 爬蟲範圍規則沒有在主機名結尾封口,10.0.0.5 的規則也會比中 10.0.0.50 — C4 F3(2:1)
239 網路診斷的 DNS 探測收回覆沒有總時限、不檢查回覆是誰送的,有人一直丟垃圾封包這次診斷就永不結束、之後所有網診卡住到重啟 — C7 F1(3:0)
240 代理伺服器網址沒寫 http:// 時,「遮帳密」函式把原字串連密碼整段吐回,進儀表板、報告、診斷包 — C8 F1(3:0)

人工查到、判定不開卡的觀察(記錄用)

各棒 runner 照卡上「重點看什麼」逐條人工補查,另記下約 15 條「設計取捨」或「縱深防禦建議」,都不算漏洞:清冊接受 0.0.0.0/0 萬用網段(主系統本來就能列任何 IP)、舊清冊可回放(版本只比相同不比大小)、啟動閘不擋清單外多出的檔(要先有 root)、裝置指紋兩來源都讀不到時退化成固定值(靠主系統撞號偵測)、SonarQube 源碼包內的 sonar-project.properties 沒刪、ZAP 逾時使用者可改到沒上限、ZAP 報告原樣上傳不遮蔽、票券重放紀錄只在記憶體(重啟即忘,註解寫明刻意接受)等。全部列在各棒報告的「重點看什麼逐條人工查證」表與總表 §3.1 各項尾註。


§3

三、四個反覆出現的模式

① 路由層把使用者輸入原樣交下去,沒有每工具/每欄位的白名單。#223、#224、#229、#232、#233 五條根因相同:主控台路由只擋底線開頭的參數鍵、清冊只比對固定幾個鍵名,其餘什麼都放。第三期 C1~C4 從 connector 內部再看,確認 connector 自己也沒有再擋一層。修一處(路由層改成每工具列舉可收的鍵)就能一次關掉五條。

② 「位址可以改,但沒有要求重填祕密或提升權限」。#227 LDAP 來源與 #232 工具位址都是同一件事:改了連線對象,舊的祕密會自動送到新對象。我們的資安需求 SR-06.3 明寫要擋,LDAP 設定頁有擋、工具設定頁沒有,是同一個人寫的兩頁行為不一致。

③ 「該踢的時機沒踢」。#220、#221、#228 三條都是登入狀態的生命週期:沒有絕對上限、改密碼不撤銷、縮權不撤銷。同一支 改三處。

④ 「連外部工具時不驗對方身分」。C2-F2 InSpec SSH 不驗主機指紋、C4-F1 連 ZAP 明文且不驗憑證、#238 連 OpenVAS 不驗憑證,三條都是 Agent 對客戶自備掃描工具的連線沒有「確認對方真的是那台」。Agent 對主系統的連線這點做得很嚴(A1/B6b 核實無任何關閉驗證的路),對掃描工具卻全漏,是同一支程式裡兩套標準。

另外兩個單點但要特別講:#234 手動升級路徑與自動路徑的防線不對稱,自動路徑三道鎖都在、手動路徑漏了驗章那一道;C2-F2 InSpec 不驗主機指紋與 OpenSCAP/Nmap 不對稱,三支同型接頭只有一支漏。這兩條都是「同一件事做了兩遍、一遍對一遍錯」,修法是對齊到對的那一邊。


§4

四、建議怎麼修:六張修正卡(方向)

併卡原則:同一根因併一張、同一支程式併一張;嚴重度高的先。每張的函式級修法在工程師版。

卡 修什麼 方向
🔴 ① 主控台與清冊的輸入白名單 #223 高、#224、#229、#232、#233、#231 主控台路由改成「每個工具列舉可收的欄位」;手填規則包拒收;清冊改成預設拒絕、網址目標只收 IP;登入入口加大小上限;改工具位址強制重填密碼
② LDAP 設定只准本機管理員 #227、#230 改 LDAP 來源與伺服器的權限從「設定」提升為本機管理員;一改就踢掉所有 AD 登入
③ 登入狀態生命週期 #220、#221、#228、#222 登入狀態加絕對上限;改密碼踢掉其他登入;主系統縮權也踢;AD 登入失敗補到固定時間
④ 手動升級路徑補驗章 #234 手動升級比照自動升級,先用現行版驗新版的原廠簽章才執行新版腳本
⑤ 兩條 DoS 與兩條可用性 #225、#226、#239、#240 8443 握手加逾時並移出接連線的執行緒;壓縮檔逐成員計數;DNS 探測加總時限;代理帳密遮罩補 scheme
⑥ 接頭連線驗對方身分 InSpec 主機指紋、ZAP 加密、OpenVAS 憑證、ZAP 爬蟲封口 三支掃描工具接頭比照 Agent 對主系統的做法,連線前確認對方身分;工具設定加「CA 憑證」欄位一次給三支用

零碎:#219 私鑰建檔權限併進 ①或 ⑤。

要寫測試:卡 ①、②、⑥ 屬認證/授權核心,要寫單元測試並附突變測試(把修法註解掉要紅)。手測:卡 ① 在 DEV Agent 主控台填外部網址當規則包要被擋;卡 ④ 在 190 測試機用改過一個 byte 的假交付包跑升級要被擋。

§5

五、先修哪些、為什麼

  1. 卡 ①(含 #223 高)先做。它是唯一不需要特殊位置、只要一個正常權限的帳號就能拿到 Agent 主機控制權的;而且一張卡關掉六條。
  2. 卡 ④ 與卡 ⑥ 次之。#234 與 C2-F2 都是「同型的三條路,兩條對一條錯」,修法是抄對的那一邊,工作量小、風險低,但後果(主機 root、客戶稽核帳密)大。
  3. 卡 ② 要先問產品:LDAP 設定收到只准本機管理員,會不會擋到客戶正常的 IT 管理流程。
  4. 卡 ③、卡 ⑤ 可排一般迭代。

落地版判準:上面全部是落地版客戶內網打得到的,沒有「只影響 SaaS 可暫緩」的項目。


§6

六、這次檢查可信到什麼程度

第一層:「這些問題是真的嗎」→ ✅ 可信

  • 每條通過的發現都經三位獨立檢查員從「打不打得到」「後果多大」「有沒有別的防線」三個角度投票;25 棒 32 條候選、96 張票全部投出、零漏投。通過 22 條(3:0 為主,三條 2:1)、否決 10 條。
  • 首腦對每條通過的發現開檔核對;#223 四段逐行核對攻擊路徑;#234 核對手動路徑與自動路徑的時序對照。
  • 唯一例外:#219 是 runner 人工發現、未經面板,首腦核對程式邏輯屬實,但實際風險取決於安裝腳本有沒有先鎖目錄(沒查)。
  • 兩處「採信檢查員讀第三方套件原始碼」:C2 train-core 預設不驗 host key、C4 zapv2 寫死 verify=False,首腦沒有重讀 gem/site-packages。

第二層:「是不是只有這些」→ ⚠️ 中等,不能說「掃乾淨了」

  • 用的是 low effort:每棒一位研究員讀全範圍、不做威脅建模、不做廣度掃描。工具有隨機性,同一份程式再掃可能找到不同的東西。
  • 六棒工具零候選(A1、A3、B6b、B8、C6,與否決後歸零的 A5、A8、C3):verified 在那裡的意思是「沒東西可投」,不是「有人確認乾淨」。這五棒靠 runner 照「重點看什麼」逐條人工補查,每棒補查 6~8 項並寫下結論。
  • 全部結論來自讀程式碼,沒有執行任何程式、沒有實際打過。#225(8443 握手卡住)、#226(tar 計數吃記憶體)這類 DoS 是讀 werkzeug/tarfile 原始碼推論的,沒有實測。

比前六輪可信的地方

  • 25 棒全部跑完,無一棒面板中斷、無一棒 runner 缺交,首腦不必補寫任何一份報告(前六輪首腦補了十一次)。
  • 每棒都有「重點看什麼逐條人工查證」表,「讀過但沒報」與「根本沒讀到」分得開。

§7

七、這次換到的三條經驗

① 工作坊可以跑掃描卡。claude-security 只接受使用者回合的啟動句,前六輪都要決策者親手打;這次工作坊加了「每張卡一支開場 prompt 覆寫檔」,把啟動句當小弟 session 第一句送進去,25 棒全部自動啟動。工作坊的停滯判定(session busy 就不判卡死)也在真掃描上驗過。

② 全中文 docstring 的程式,安全線是 1,000 行不是 2,000。Agent 的註解密度是英文碼的兩三倍 token,第一期按 1,000 行切,25 棒零看門狗誤殺;第三期 C1 單檔 1,711 行、10,364 個中文字也跑完了(研究員 2/2、零 failed),C2 單檔 1,050 行、C8 十檔 1,291 行也都零 failed,表示「單檔一次讀完不追接縫」比行數更關鍵,並行四棒也沒影響。

③ 人工補查抓到的不比工具少。工具通過 19 條,runner 照首腦列的重點人工補查另抓到 #219 一條中、約 15 條觀察,並且把五棒工具零候選的範圍填上了「讀過」的證據。「重點看什麼」是這套方法裡成本最低、回報最高的一段。


§8

八、第三期八棒看到什麼

第三期掃的是 Agent 組參數去跑外部工具的地方。首腦開卡前最擔心的三件事,結果如下:

擔心的事 結果
遠端字串指令(Nmap/OpenSCAP 在客戶主機上以 sudo 跑)有欄位漏 shlex.quote 不成立。C3/C5 逐欄核對,三個值全部 quote;sudo 只在 syn 掃描
網路診斷探測把使用者填的目標原樣進 argv,- 開頭被 ping 當成選項 不成立。進探測前一律先過 ipaddress.ip_address(),只有合法 IP 才往下走
診斷報告把探測原始輸出渲染成 HTML 沒跳脫 不成立。一律 html.escape 且報告不存 .html

真正找到的是另一族:三支接頭連客戶自備的掃描工具時不驗對方身分(InSpec 主機指紋、ZAP 明文、OpenVAS 憑證),加上兩條低風險的可用性問題(DNS 探測可被卡死、代理帳密沒遮)。C1 SonarQube 與 C6 SBOM 在工具層淨新增零,人工補查各記了三條不開卡的觀察。

Semgrep 事前掃整個第三期範圍只命中一條(程式 subprocess 吃 env),第三期六條發現沒有一條是規則掃描器抓得到的,全部是「程式寫法正確(list argv、quote 過)但對象錯或少一道驗證」這類要靠讀程式才看得出的問題。


§9

九、交付狀況

項目 狀態
逐棒報告 25 份 正本 Agent repo docs/security-scan/FR-177/,複本本資料夾 reports/
工具原始產物(run 目錄)25 份 security-scan-consolidated/runs/agent/
跨 arc 總表登記 §0.5 Agent 一列、§1 165 輪、§3.1 #219~240
Notion 母卡 CM-3507;子卡 25 張(CM-3508~3532)全部「驗收通過待確認」,Done 由決策者按
修正卡 未開,等決策者裁第四節六張的併法與第五節順序
本報告 PM 版(本份,無程式位置);工程師版(含檔名行號與函式級修法)在 Agent repo docs/security-scan/FR-177/SUMMARY-engineering.md,不上站

等決策者裁的事

  1. #223 要不要在第三期驗完前就開修正卡(建議:要,它不等其他條)。
  2. 第四節六張修正卡的併法與第五節順序,裁了首腦開卡進工作坊。
  3. 卡 ② LDAP 設定收到只准本機管理員是否符合客戶 IT 流程。
  4. 逐棒報告 25 份含未修漏洞的檔名與行號,複本目前在 feature/FR-172 分支的 docs/features/FR-177/reports/,合回 main 會隨需求文件站上線。總結報告已拆成 PM 版(上站、無行號)與工程師版(Agent repo、不上站);逐棒報告複本要不要也從 docs/features/ 拿掉、只留 Agent repo 正本,請裁。