security-scan · 需求索引 · 本頁由 build 掃資料夾生成

資安掃描總彙整(FR-075/076/077/078/079/081 + 2026-07 舊 arc)

狀態:彙整報告,2026-09-09 產出。掃描結論、修正卡狀態、未開卡待辦、覆蓋率地圖四合一 文件 0 份

資安掃描總彙整

這份檔在回答一個問題:掃了那麼多,結論是什麼、還有哪些要修。 六個掃描 arc 的報告各自在自己的 FR 資料夾,這裡只做跨 arc 收斂——不重複細節,每條都給座標。 逐條技術細節請點各棒報告;現況與派工紀律看 FR-075/handoff/security-scan-STATE.md


0. 三十秒版

  • 掃了 6 個 arc、21 棒,涵蓋 jedi-iam(290 檔)、License 鏈(118 檔)、遠端 Agent(部分)、jedi-notification、jedi-bulletin,另有 2026-07 的主專案 BE/FE 工具掃描。
  • 累計成立的資安發現約 60 條,開出 34 張修正卡24 張已 Done9 張待派/Not started(含 1 張 CRITICAL)、1 張暫緩。
  • 最急的一張到現在沒動CM-1595(遠端 Agent 控制面四端點完全不驗身分,CRITICAL,免登入即可取走客戶機器的明文憑證)。它「沒派」是決策者裁定「PM 統一安排修正」的結果,不是漏掉。
  • 另有 12 項掃出來但還沒開卡(見 §3),其中 4 項是真 bug 只是不算資安。
  • 25 支 jedi- 套件裡只掃過 5 支*,jedi-common(全部套件的地基)至今沒有一次算數的掃描。

1. 掃描棒次進度(21 棒)

Arc 對象 結果 報告
FR-075 jedi-iam(290 檔/7 棒) S1 認證與外部身分 ✅ 8 條(5H 3M) 報告
S2 授權守門 ✅ 0 條(首腦仍加開 CM-1559) 報告
S3 MFA+Turnstile ✅ 2 條(1H 1M) 報告
S4 使用者與密碼 ✅ 5 條(2C 1H 2M) 報告
S5 角色與權限 ✅ 2 條(2M) 報告
S6 租戶與組織 ✅ 1 條(1M)+3 條非資安真 bug 報告
S7 登入態/middleware ⚠️ 無效——9 條裡 8 條越界重複 S1,核心範圍從未被掃 報告
FR-076 License 鏈(118 檔/4 棒) L1 驗章核心 ✅ 1 條範圍內 HIGH(解壓炸彈) 報告
L2 授權狀態 API ✅ 1 LOW +人工另發現 1 HIGH(停權可換照解除) 報告
L3 LC 簽發核心 ✅ 1H 1M(序號僅 32 bits/log 遮蔽失效) 報告
L4 LC 網頁後台 ✅ 4M(開通端點防猜失效、開放導轉) 報告
FR-077 遠端 Agent(⏸ 暫停 R1 agent 身分與註冊 ⚠️ 7 條(1C 2H 3M 1L),面板全滅、覆蓋率不可宣稱 報告
R1b/R2a/R2b/R3 ⬜ 卡開好、範圍寫死,未派
FR-078 jedi-notification N1 套件本體 ✅ 2 條(2M,SMTP 密碼進 log/starttls 不驗憑證) 報告
N2 宿主接線 ✅ 6 條(2H 3M 1L,其中 4 條範圍外憑證) 報告
FR-079 jedi-bulletin B1 套件本體 ✅ 工具 0 條+人工 3 條(皆目前打不到) 報告
B2 宿主接線 ✅ 10 條(4 條範圍內、6 條範圍外憑證) 報告
FR-081 jedi-issue I1~I6(六棒) ⬜ 全部待派(決策者裁一次只派一棒) 索引
2026-07 舊 arc 主專案 BE/FE Sonar/Semgrep/Trivy ✅ 已收官(v1.10.1 清理完成) 索引

兩棒的結果要打折看

  • S7 等於沒掃——研究員越界跑去重複 S1,middlewaredomain serviceplugin.py 預設值/login_logui_route 從未被讀過。決策者已裁重跑。
  • R1 的七條可信、「只有七條」不可信——三人驗證面板 105 個 verifier 全部撞額度上限,0 票投出。七條是 runner 與首腦各人工開檔核對兩遍確認的(事實陳述,不是推論),但覆蓋率無法宣稱,故加開 R1b 補掃密碼學核心。

2. 修正卡總表(34 張)

2.1 ✅ 已 Done(24 張)— 不用再看

修什麼 嚴重度
CM-1575 忘記密碼端點外洩重設憑證 🔴 CRITICAL
CM-1557 MFA 驗證碼無次數限制 HIGH
CM-1560 LDAP 三洞(匿名 bind/filter escape/TLS 不驗證) HIGH
CM-1562 綁定外部身分無本人檢查 HIGH
CM-1561 Google 登入殼(裁定:關閉不拔除) HIGH
CM-1576 自助 profile 自我提權 HIGH
CM-1572 驗章前無界解壓縮(解壓炸彈) HIGH
CM-1579 停權可被換照解除 HIGH(SaaS)
CM-1583 LC 開通端點七項(防猜/計數表/log 遮蔽/補發復活) HIGH
CM-1558 Turnstile 缺金鑰 fail-open MEDIUM
CM-1563 帳號枚舉統一 401 MEDIUM
CM-1564 LDAP 連線測試改位址強制重輸密碼 MEDIUM
CM-1565 Redis TLS 不驗憑證 MEDIUM
CM-1573 jedi-issue PAT 外洩處置 MEDIUM
CM-1577 update_user 改密碼不驗強度 MEDIUM
CM-1578 Excel 上傳目錄用未驗證 login_name MEDIUM
CM-1584 LC 登入 next 開放導轉 MEDIUM
CM-1585 角色讀取端點無守門 MEDIUM 偏 HIGH
CM-1586 失效角色算成有效 MEDIUM
CM-1587 全站請求 body 上限(裁 50MB) MEDIUM
CM-1588 租戶/部門部分更新清空上層歸屬 MEDIUM
CM-1589 部門/租戶/使用者讀端點補 .read 守門 MEDIUM
CM-1580 跨租戶重複用照部分唯一索引 LOW
CM-1581 build 公鑰守門路徑 bug 小 fix

⚠️ 這 24 張多半只進了 DEV/套件源碼,還沒發版上 STG/POC——見 §5 上版待辦。

2.2 🔴 待派/Not started(9 張)— 這是「還有哪些要修」的核心

按嚴重度排序。全部未動是決策者裁定「PM 收集完所有掃描結果再統一安排」的結果,不是漏派

修什麼 嚴重度 來源
CM-1595 Agent 控制面四端點不驗身分(register/heartbeat/ack/result)。免登入即可自報 agent_uid 取走該租戶掃描工具明文憑證(SonarQube token/SSH/WinRM 帳密);跨租戶亦可;ack/result 可偽造或抹除稽核證據。宣稱倚賴的 nginx mTLS 出貨設定裡不存在 🔴 CRITICAL FR-077 R1 F1+F2+F3+F5
CM-1605 測試信端點把平台 SMTP 密碼送到呼叫端指定的主機。子租戶管理員可拿走營運方郵件帳密,之後用貴公司名義寄信且通過 SPF 🟠 HIGH FR-078 N2 F1(+F5 Discord SSRF 併入)
CM-1597 enroll token 永久有效+可重註冊接管同租戶任一台 agent(依賴 1595,序列做) MEDIUM FR-077 R1 F6
CM-1596 健康檢查端點 SSRF(可當內網掃描器,需租戶管理員) MEDIUM FR-077 R1 F4
CM-1606 SMTP adapter 兩洞:密碼原樣寫進 log + starttls 不驗憑證 MEDIUM×2 FR-078 N1
CM-1607 清版控內殘留的已撤銷金鑰(conversation-history 13 檔+Trivy 報告 2 檔+FR-079 F12 的 JWT 金鑰 31 檔);並評估 CI 加秘密掃描 衛生 FR-078+FR-079
CM-1608 拔掉腳本硬編的 POC DB 密碼與 blsadmin 密碼。決策者裁測試機專用、密碼不需更換,只做程式碼衛生(os.getenv(..., "<真密碼>") 這個 pattern 本身錯誤) 衛生 FR-078 N2 F4/F8
CM-1598 jedi-common/.env 受版控(目前值無真密碼,風險是結構性的) LOW FR-077 R1 F7
CM-1559 RLS fail-opensession_scope 無 user context 時預設 super admin)。影響面最廣,盤點已完整回寫 Notion 卡,等決策者裁修法方向 MEDIUM(優先級可降,見下) FR-075 S2 首腦加開

CM-1559 的關鍵更新:盤點發現 X-Tenant-ID: 0 這條利用路徑已被 FR-069.16 擋死context.py 加了隸屬檢查)。根因仍在,但已不是可利用的漏洞,故優先級可降。runner 建議下刀順序是「先拿掉 not tenant_id 條件(爆炸面只有 signed_token 一條路徑),再改 elif is_pg 為 fail-closed(動全站 session 進入點)」。

2.3 ⏸ 暫緩(1 張)

內容 綁什麼條件
CM-1582 客戶包公鑰白名單(出包按環境只編 PROD 鑰,DEV 鑰不進客戶包) 綁正式 LC 建立

3. 🔴 掃出來但還沒開卡的(12 項)

這一段最容易漏——它們散在各報告的「建議開卡」段落裡,沒有進 Notion。

3.1 資安類(6 項)

# 內容 嚴重度 出處
1 公告授權補強四合一:AI 儀表板旁路可讀全租戶公告(含草稿,且前三筆原文送第三方 LLM)/改刪公告不驗歸屬且靜默清空發送對象/單筆讀取零檢查/列表對無部門帳號直接全放行 MEDIUM×2+LOW×2 FR-079 B2 F13/F16/F17/F18
2 憑證輪替與清除cmmgr DB 密碼(BYPASSRLS)/四家 LLM API 金鑰(9 檔)/Nexus+MinIO 憑證(供應鏈的根)/migration 腳本把真密碼當環境變數 default MEDIUM×4 FR-079 B2 F1/F2/F3/F14
3 installer 每套部署種同一組原廠 super admin 密碼,bcrypt hash 寫死在 SQL、不強制首次改密 MEDIUM FR-079 B2 F15(決策者裁:先記錄,之後看怎麼調整
4 bulletin_org_units RLS 未設(走 sql-migration SOP) FR-079 B2 重點⑩
5 三張表有 RLS policy 但 RLS 沒啟用compliance.projectsworkflow_executionsworkflow_templates,且 projects 的 policy 沒有 super admin 分支。現在不會出事(policy 沒生效),哪天有人打開 RLS 會直接壞 定時炸彈 CM-1559 盤點順帶發現
6 三環境硬編公鑰:DEV 私鑰簽的照 POC 也認。決策者已裁「現階段不急,綁正式 LC 一併處理」,但尚未落成卡 綁正式 LC FR-076 L1

3.2 非資安但是真 bug(4 項)

面板判定「不是資安問題」,但程式碼缺陷是確認過的,值得開一張非資安卡順手修:

# 內容 位置
7 PUT /tenant/<uid>PUT /org-unit/<uid> 部分更新會parent_id 打成 NULL,留下 parent_idpath 互相矛盾的資料列 tenant_repo_impl.py:44org_unit_repo_impl.py:52
8 建部門時 created_user 從未被設定(連續兩行都寫 updated_user),兩個稽核欄位都寫成 NULL app/service/org_unit_service.py:74-75
9 套件版 update_bulletin() 檢查錯對象(if not bulletin 應為 if not bulletin_model),查無此筆時對 None 設值直接 500 jedi-bulletin bulletin_repo_impl.py:56
10 無登入者時建立公告會崩潰(對 None.uid)——好消息是它「炸」而不是靜默寫 NULL 建立者 jedi-bulletin bulletin_service.py:50/62

9、10 兩條目前打不到(套件那支 service 沒有任何呼叫者,主專案走自己那支)。

3.3 掃描本身的補洞(2 項)

# 內容
11 S7 重跑(CM-1556)——決策者已裁,尚未執行。重跑要收窄掉 infra/adapter/authenticate_adapter/user_auth_provider_service.py 避免再度越界重複 S1
12 R1b 補掃(CM-1599)——只掃 common/agent_auth/ 10 檔的密碼學核心(簽憑證 ca.py/簽 JWT jwt_util.py),R1 面板全滅時這塊分不出「讀過」還是「沒讀到」

3.4 兩項「等於沒查」,不能當作乾淨

  • 公告 content 的儲存型 XSS——需開 FE repo 查渲染方式,B2 本棒未查。
  • 審計欄位 subquery 是否繞過 users 表 RLS——B2 本棒未查。

4. 覆蓋率地圖:掃過的 vs 沒掃過的

25 支 jedi- 套件,實質掃過 5 支。 未掃合計約 111 棒、133 小時*(純掃描,不含驗收/開卡/修正)。

狀態 套件
✅ 掃完 jedi-iam(S7 待重跑)、jedi-license-runtime、jedi-notification、jedi-bulletin
🔄 部分 jedi-remote-agent(R1 完成、餘暫停)、jedi-detection(僅 agent 相關 11 檔,餘 140 檔未掃
⬜ 已開卡待派 jedi-issue(六棒 CM-1613~1618)
⚠️ 不算數 jedi-common——只有第一輪未經面板的半途掃描
⬜ 完全沒碰 其餘 17 支

首腦建議的下一批順序(按風險,不是按檔數):

  1. jedi-common(92 檔/8.4h)——全部套件都 import 它session_scope@transaction/RLS 注入/error handler 都在這,CM-1559 的根也在這。它出問題等於 25 支全中。
  2. jedi-integrity(20 檔/2.4h)——CP 值最高,全是簽章與完整性驗證,FR-076 已在它身上順手撞到一條 HIGH。
  3. jedi-file-upload(61 檔/6h)——路徑穿越與任意檔案讀取的天然溫床。
  4. jedi-detection 剩下的 140 檔——客戶憑證解密在這,掃描參數會變成 agent 端執行的指令。
  5. jedi-participant(103 檔)——jedi-iam 管「你是誰」,這支管「你在這個專案能幹嘛」。

jedi-oscal-v2(364 檔)建議獨立 arc:風險形狀不同(XXE/解析炸彈/資源耗盡),混進授權鏈掃描會讓卡片失焦。

兩個排計畫時的陷阱(FR-077/FR-079 換來的)

  1. 「某某套件掃過了」這句話要問範圍——看報告要看 scope 清單,不是看套件名。
  2. 排名表的檔數只涵蓋套件本體、不含宿主接線——jedi-bulletin 被列為「攻擊面小」,但「誰能看到哪一則公告」的判定整個在主專案的 33 檔裡,十個重點有八個落在宿主側。排下一支時要先問「這支有沒有宿主那一半」。

5. 上版待辦(修正做完了,但還沒進 STG/POC)

24 張 Done 的修正卡多數只在套件源碼與 DEV,尚未發版:

  • jedi-iam:13 張修正卡待發版 → 主專案 pyproject.toml pin → 重出 image → 部署 STG → 部署 POC
  • License Center:CM-1583/1584 走 LC 部署四步;1583 帶兩支 alembic migration(皆 nullable)需套 STG/POC
  • 主專案 BE:CM-1580 的部分唯一索引 migration 需套 STG/POC(DEV 已建)

⚠️ 上版行為變化提醒(會直接擋連線,上版前先確認):

  • CM-1565(Redis TLS):若 STG/POC 已開 TLS 但憑證有問題,上版後會直接擋連線。
  • CM-1560(LDAP TLS):上版後預設驗憑證,若有接 LDAP 且憑證未配置好會連不上。

6. 等決策者裁的事項(5 項)

  1. CM-1559 修法方向——盤點已完整回寫 Notion 卡,等裁「先下第二刀再下第一刀」這個順序可不可以、以及三類分流的範圍。
  2. S7 重跑時機——已裁要重跑,未排。
  3. 上版時機——jedi-iam 13 張 Done 修正卡何時與 LC 一起發版上 STG/POC。
  4. CI 加秘密掃描(gitleaks/trufflehog 擋在 pre-commit 或 CI)——新增基礎設施要決策者裁。
  5. 下一支掃哪個套件——FR-081 六棒待派中;再下一支首腦建議 jedi-common 或 jedi-integrity。

已裁決、不要重問的:POC DB 與 blsadmin 密碼不需更換(測試機專用)/不重寫 git 歷史(.env.test 事件)/修正卡一律不派由 PM 統一安排/FR-079 F12 降衛生類併 CM-1607/F15 先記錄不開卡。


7. 座標

要什麼 去哪
現況與派工紀律(living) FR-075/handoff/security-scan-STATE.md
歷程(append-only) FR-075/handoff/security-scan-LOG.md
首腦手冊(切棒/開卡/驗收/裁決) .claude/skills/security-scan-lead/SKILL.md
工具用法與失敗紀錄 FR-075/scan-methodology.md
2026-07 工具掃描原始產物 `docs/security-reports/2026-07-24
建卡腳本 scripts/notion_create_case.py

母卡:FR-075 CM-1546/FR-076 CM-1566/FR-077 CM-1591/FR-078 CM-1602/FR-079 CM-1609/FR-081 CM-1612。