FR-108 弱點掃描整合套件(jedi-detection)資安掃描 — arc 收口 SUMMARY

給誰看:決策者排修正順序時、下一任首腦接手掃描 arc 收口時、任何想知道「這支套件掃出什麼」的人。細節在各棒報告與跨 arc 總表,本頁只收斂。

🔴 一頁看完

這支套件的風險集中在兩條線:憑證怎麼存與怎麼出(D1/D3),以及規則包怎麼解析(D2)。 14 批 83 檔掃完,找到 2 條高風險:第 85 項——「測試連線」端點忘了檢查權限,客戶公司裡任何登入者都能叫系統把存好的第三方掃描工具帳密解密送到自己指定的主機;第 115 項——客戶上傳(或填網址指向)的掃描規則包會被外部程式 cinc-auditor 當 Ruby 樣板先跑一遍,等於任意程式碼在後端主機上執行,拿到的是整台機器與 cmmgr 繞租戶隔離的資料庫存取權。兩條都只需要「先是登入的租戶/專案管理者」這一道門檻,過了就沒有第二道。

最該先處理的一條(第 115 項):修法是在重打包之前先看一眼 inspec.yml 有沒有 ERB 樣板標記(<%),有就拒收,並把 cinc-auditor 關進沙箱跑;第 85 項修法極便宜,補一行權限宣告即可。

十四批結果

棒 卡 範圍 淨新增 報告
D1 工具目錄+租戶憑證+守門殼 CM-1873 36 檔 4 條(1 高 3 中→第 85~88 項) scan-D1
D3-1 結果回收 CM-1875 4 檔 859 行 1 條中風險(第 101 項) scan-D3-1
D3-2 任務綁定 同上 5 檔 1,328 行 1 條中風險(第 105 項) scan-D3-2
D3-3 狀態機與存取層 同上 11 檔 707 行 0(第 88 項重複,補行號) scan-D3-3
D3-4a 編排:派工/取消/刪除 同上 1,151 行 1 條中風險(第 107 項) scan-D3-4a
D3-4b 編排:回收/狀態/排程 同上 1,350 行 0(第 107/59+88/105 項重複,補第 59 項影響面) scan-D3-4b
D2-1a 上傳入口守門 CM-1874 3 檔 1,058 行 2 條中風險(第 113/114 項) scan-D2-1a
D2-1b 壓縮檔封存驗證 同上 2 檔 422 行 1 條中風險(第 112 項) scan-D2-1b
D2-2a 基準服務本體 同上 1 檔 1,133 行 1 條中風險(第 117 項) scan-D2-2a
D2-2b 基準領域與存取層 同上 4 檔 499 行 0(人工另記體質項,§3.2) scan-D2-2b
D2-3 解析與外抓 同上 4 檔 1,677 行 2 條:1 高 1 中(第 115/116 項) scan-D2-3
D2-4a 分類骨幹全鏈 同上 8 檔 772 行 0(人工另記體質項,§3.2) scan-D2-4a
D2-4b 版本存取層與規則清單 同上 8 檔 837 行 0(與第 105 項同鏈,獨立重現) scan-D2-4b
D4(骨架殼) CM-1876(作廢) 併入 D1 — —

面板全程零漏投;D2-1/D3 前段多次撞上上游看門狗誤殺(bug #92424),改小棒重試後皆跑完,實際結論沒有因此漏查。

十三條資安發現(登記跨 arc 總表 §3.1)

# 嚴重 白話 在哪 怎麼修
85 🔴 高 「測試連線」只驗登入,任何人按一下就把掃描工具帳密解密外送 檢測工具設定頁 補一行權限宣告,照抄同檔寫入端
86 中 「測試連線」的目標主機照單全收,等於內網跳板 同上 目標限已登記的掃描目標或白名單
87 中 資料庫客戶隔離規則方向寫反,子單位反而看得到母單位,出貨基線共 9 條 migration 9 條換成正確寫法,跨三個套件一次改
88 中 掃描歷史查詢少了專案參與者檢查 D3 那支檔 補上同服務其他八處已在用的參與者檢查
101 中 代理程式回報報告時檔名叫什麼就存什麼,.html 會被當網頁執行 D3-1 副檔名白名單,或乾脆自己命名
105 中 換掃描工具時「要掃哪些機器」不重新檢查台數上限,可把範圍填成超大網段 D3-2(D2-4b 獨立重現同一條) 用實際生效值重查,兩個入口都補+加硬上限
107 中 開始掃描時把客戶機器帳密另存一份明文進工單表,沒人讀也永不清理 D3-4a 刪掉那一行+補一支清存量的 migration
112 中 上傳規則包的「最多一萬個檔」上限對 .zip 形同虛設,記憶體先被吃光 D2-1b 打開前先讀 zip 檔尾目錄筆數擋掉
113 中 宣告了「檢視掃描設定檔」權限,七支讀取功能一支都不檢查 D2-1a 七支補上同檔已有的能力點裝飾器
114 中 手動重抽功能無併發上限,連打幾百次可把主機打掛 D2-1a 服務裡已有 running 狀態,retry() 補判斷即可
115 🔴 高 客戶上傳的規則包被當 Ruby 樣板執行,等於後端 RCE D2-3 打包前檢查 ERB 標記並拒收,cinc-auditor 關進沙箱
116 中 網址型來源完全跳過壓縮檔驗證器的三道防炸彈上限 D2-3 上限改放在解析器本體,不是服務層呼叫點
117 中 填網址建基準時放行明文 http://,且不記指紋供代理程式核對 D2-2a 只收 https://;第一次抓下來記指紋、之後每次核對

現況(2026-10-01):上表 13 條資安發現全數已修,隨 1.21.0 出貨,對應 M03 頁:第 85 項=M03-2(CM-2042)、86=M03-6(CM-2058)、87=M03-7(CM-2271)、88=M03-12(CM-2040)、101=M03-13(CM-2062)、105=M03-11(CM-2058)、107=M03-9(FR-114.4-3)、112=M03-4(CM-2057)、113=M03-8(CM-2042)、114=M03-10(CM-2058)、115=M03-1(CM-2057)、116=M03-3(CM-2057)、117=M03-5(CM-2057)。 六條非資安:第 28/29 項 ✅ 已修(CM-2221,1.21.0 出貨);第 30~33 項為註解與前提類記錄,查不到單獨處理紀錄,保留待核。

六條非資安程式錯誤(§3.2 第 28~33 項):28/29 是 SHARED scope 三處值域不一致(建立擋、修改不擋)+套件自帶建表腳本仍是舊值域;30 是分類引用計數方法的註解與實際隔離行為相反(現況安全但誤導);31 是基準領域/存取層四檔零租戶隔離程式碼、安全性完全外包 RLS(現況成立但沒有第二道防線);32 是 detection_profile_controls 的零隔離保護完全靠約定沒有機制強制——list_by_version_id() 是公開方法,今天三個呼叫端都守規矩,第四個寫錯的人不會看到任何錯誤訊息,只會悄悄拿到別租戶資料;33 是 jedi-common 的 _get_pager_list_query 分頁查詢把跨欄位字串條件用 OR 而不是 AND 連接——同時傳 scope='TENANT' 與 name='foo' 得到的是「符合任一條件」而非「兩者都符合」,不構成跨租戶外洩(RLS 仍擋著)但會讓呼叫端拿到超出預期的清單。

這份結果可信到什麼程度

  • 「這些發現存在嗎」:可信。14 批面板全數跑完(多次因上游看門狗誤殺重試,但重試後皆完整跑完投票),每條高/中風險首腦逐條開檔核對行號與內容,其中第 105 項被 D3-2 與 D2-4b 兩組不同研究員、不同範圍切法獨立重現,交叉驗證強。
  • 「只有這些嗎」:不能這樣說。全程 effort=low、多為單研究員跑法,卡片重點靠 runner 人工核(多數未經投票);D2-2b/D2-4a/D2-4b 三棒工具零候選,實質產出全靠首腦逐項開檔查證。全程沒打過任何端點、沒連過外部主機,全是讀碼推論。
  • 答不了的:主專案接線層(core/plugins/detection.py 362 行、三顆 DI 容器、兩支 readmodel、兩支 adapter,共 14 檔)尚未掃,套件側只答得了「套件自己這一層」;R2b 那 11 支(代理程式端 auth/connector)屬 FR-077 CM-1601 另案。

等決策者裁(掃描收口當時;2026-10-01 同步:第 1 項已照問題總表統一派工並修完,第 2 項經查情境不成立、只記錄不處理(M03 報告),第 3 項主專案接線已由 FR-115 W3 補掃)

  1. 修正卡怎麼開——決策者已裁全掃完統一開,本 arc 14 條發現+6 條非資安 bug 尚未開卡,需要一次性排優先序。
  2. 出貨基線待重產——套件自帶建表腳本值域舊(28/29 項)+ RLS 腳本缺 SHARED 分支(31 項備註),既有環境不受影響但新裝客戶會撞到,重不重產待裁。
  3. 主專案接線層要不要排(14 檔約 362+ 行,含 DI 容器與 adapter)。

流程教訓(已記 STATE 與 memory)

  • 切棒判準要改成「小到重試會成功」而不是「小到不會被砍」:D2-4b 837 行仍被砍兩次但第三次撐過去,證明行數小不保證不被砍、但保證撐得住重試。
  • 檔案性質是主變數、行數是次要:含 route 的檔會把研究員引向下游接線(service/guard/DI/宿主),token 消耗遠高於自包含模組;route 檔行數要乘倍數算 token 預算,不是單看行數。
  • 重複比對必須是驗收固定動作:D2-4b 與 D3-2 撞同一條,若不比對會誤登記成新風險、重開一張修正卡。
  • 「證明沒有」的報告要寫得跟「找到有」一樣仔細:D2-2b/D2-4a/D2-4b 三棒的零發現結論全靠首腦把追查路徑寫清楚,否則等於沒查。
  • 看門狗誤殺判準已更正:不是數 journal 的 failed 事件(這個工具版本不寫這個字),而是數「failed+同 label 重複 started」,第二次出現就代表研究員被砍。

commits(BE repo,branch feature/review,未 push)

D1 開卡驗收、D3 五棒、D2 八棒逐棒 commit 見 docs/features/FR-108-2609-detection-security-scan/README.md 各行內附連結報告;D2-4a/D2-2b 驗收 12f63826;D2-4b 驗收+arc 收口見本次 commit。套件 repo 無異動(只掃不修)。

座標

  • 本 arc:docs/features/FR-108-2609-detection-security-scan/(README 有逐棒切棒表/驗收記錄/各棒報告連結)
  • 跨 arc 總表:docs/features/security-scan-consolidated/README.md §0.5 已掃完套件清單、§3.1 第 85~88/101/105/107/112~117 項、§3.2 第 28~33 項
  • 共用 STATE:docs/features/FR-075-2609-jedi-package-security-audit/handoff/security-scan-STATE.md
  • Notion:母卡 CM-1872、子卡 CM-1873 D1/CM-1874 D2/CM-1875 D3/CM-1876 D4(作廢)
  • 套件路徑:~/Projects/Jedicogy/module/jedi-python-package/jedi-detection/