---
title: 資安掃描總彙整（FR-075／076／077／078／079／081 ＋ 2026-07 舊 arc）
status: 彙整報告，2026-09-09 產出、2026-09-10 併入 FR-081 六棒收口。掃描結論、修正卡狀態、未開卡待辦、覆蓋率地圖四合一。**每棒驗收完由首腦同步更新**
relates: [FR-075, FR-076, FR-077, FR-078, FR-079, FR-081]
---

# 資安掃描總彙整

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

---

## 0. 三十秒版

- **掃了 8 個 arc、29 棒**，涵蓋 jedi-iam（290 檔）、License 鏈（118 檔）、遠端 Agent（部分）、jedi-notification、jedi-bulletin、jedi-issue（158 檔）、**jedi-ai-bot（14 檔）**，另有 2026-07 的主專案 BE/FE 工具掃描。
- **累計成立的資安發現約 81 條**，開出 **41 張修正卡**：**24 張已 Done**、**16 張待派／Not started**（含 1 張 CRITICAL、2 張 HIGH）、1 張暫緩。
- **最急的一張到現在沒動**：`CM-1595`（遠端 Agent 控制面四端點完全不驗身分，**CRITICAL**，免登入即可取走客戶機器的明文憑證）。它「沒派」是決策者裁定「PM 統一安排修正」的結果，不是漏掉。
- **另有 16 項掃出來但還沒開卡**（見 §3），其中 4 項是真 bug 只是不算資安。**新增三項來自 FR-083 D2，決策者裁「先不開卡，之後從總表決定要修哪些」**——最值得看的是「任何登入者可透過 AI 儀表板列出全公司帳號，且回應夾帶密碼鹽值」。
- **25 支 jedi-* 套件裡只掃過 7 支**，`jedi-common`（全部套件的地基）至今沒有一次算數的掃描。
- **同一種病一再出現**：讀取端點漏守門已第三次（CM-1585／1589 已修、FR-079 公告待修、FR-081 意見回饋待修）；憑證被工作過程寫進版控也第三次（`.env.test`／JWT 金鑰／DB 密碼 249 檔）。**修法可以抄，但要治本得改工作方式。**

---

## 1. 掃描棒次進度（22 棒）

| Arc | 對象 | 棒 | 結果 | 報告 |
|---|---|---|---|---|
| **FR-075** | jedi-iam（290 檔／7 棒） | S1 認證與外部身分 | ✅ 8 條（5H 3M） | [報告](../FR-075-2609-jedi-package-security-audit/scan-iam-1-auth-and-external-identity.md) |
| | | S2 授權守門 | ✅ 0 條（首腦仍加開 CM-1559） | [報告](../FR-075-2609-jedi-package-security-audit/scan-iam-2-authz.md) |
| | | S3 MFA＋Turnstile | ✅ 2 條（1H 1M） | [報告](../FR-075-2609-jedi-package-security-audit/scan-iam-3-mfa-turnstile.md) |
| | | S4 使用者與密碼 | ✅ 5 條（**2C** 1H 2M） | [報告](../FR-075-2609-jedi-package-security-audit/scan-iam-4-user-and-password.md) |
| | | S5 角色與權限 | ✅ 2 條（2M） | [報告](../FR-075-2609-jedi-package-security-audit/scan-iam-5-role-and-capability.md) |
| | | S6 租戶與組織 | ✅ 1 條（1M）＋3 條非資安真 bug | [報告](../FR-075-2609-jedi-package-security-audit/scan-iam-6-tenant-org-unit.md) |
| | | S7 登入態／middleware | ⚠️ **無效**——9 條裡 8 條越界重複 S1，核心範圍從未被掃 | [報告](../FR-075-2609-jedi-package-security-audit/scan-iam-7-login-uiroute-common.md) |
| **FR-076** | License 鏈（118 檔／4 棒） | L1 驗章核心 | ✅ 1 條範圍內 HIGH（解壓炸彈） | [報告](../FR-076-2609-license-chain-security-scan/scan-L1-verification-core.md) |
| | | L2 授權狀態 API | ✅ 1 LOW ＋**人工另發現 1 HIGH**（停權可換照解除） | [報告](../FR-076-2609-license-chain-security-scan/scan-L2-license-state-api.md) |
| | | L3 LC 簽發核心 | ✅ 1H 1M（序號僅 32 bits／log 遮蔽失效） | [報告](../FR-076-2609-license-chain-security-scan/scan-L3-issuance-core.md) |
| | | L4 LC 網頁後台 | ✅ 4M（開通端點防猜失效、開放導轉） | [報告](../FR-076-2609-license-chain-security-scan/scan-L4-web-backoffice.md) |
| **FR-077** | 遠端 Agent（**⏸ 暫停**） | R1 agent 身分與註冊 | ⚠️ 7 條（**1C** 2H 3M 1L），**面板全滅、覆蓋率不可宣稱** | [報告](../FR-077-2609-remote-agent-security-scan/scan-R1-agent-identity.md) |
| | | R1b／R2a／R2b／R3 | ⬜ 卡開好、範圍寫死，**未派** | — |
| **FR-078** | jedi-notification | N1 套件本體 | ✅ 2 條（2M，SMTP 密碼進 log／starttls 不驗憑證） | [報告](../FR-078-2609-notification-security-scan/scan-N1-package-core.md) |
| | | N2 宿主接線 | ✅ 6 條（2H 3M 1L，其中 4 條範圍外憑證） | [報告](../FR-078-2609-notification-security-scan/scan-N2-host-wiring.md) |
| **FR-079** | jedi-bulletin | B1 套件本體 | ✅ 工具 0 條＋人工 3 條（皆目前打不到） | [報告](../FR-079-2609-bulletin-security-scan/scan-B1-package-core.md) |
| | | B2 宿主接線 | ✅ 10 條（4 條範圍內、6 條範圍外憑證） | [報告](../FR-079-2609-bulletin-security-scan/scan-B2-host-wiring.md) |
| **FR-081** | jedi-issue（158 檔／6 棒） | I1 第三方整合與憑證（25 檔） | ✅ 2 條（連 GitHub 不驗憑證） | [報告](../FR-081-2609-issue-tracking-security-scan/scan-I1-third-party-integration.md) |
| | | I2 宿主接線（31 檔） | ✅ 5 條（**含唯一的 HIGH**） | [報告](../FR-081-2609-issue-tracking-security-scan/scan-I2-host-wiring.md) |
| | | I3 附件上傳下載（14 檔） | ✅ 工具 0 條＋首腦補查 1 條 | [報告](../FR-081-2609-issue-tracking-security-scan/scan-I3-attachments.md) |
| | | I4 對外面與插件契約（20 檔） | ✅ 工具 0 條（兩項查證首腦補做） | [報告](../FR-081-2609-issue-tracking-security-scan/scan-I4-plugin-contract.md) |
| | | I5 app 與 domain（**40 檔**） | ✅ 1 條（Nexus 走明文連線） | [報告](../FR-081-2609-issue-tracking-security-scan/scan-I5-app-domain.md) |
| | | I6 持久層（28 檔） | ✅ 工具 0 條＋**首腦查出六張表零 RLS** | [報告](../FR-081-2609-issue-tracking-security-scan/scan-I6-persistence.md) |
| | | **總結** | **19 條歸成 6 張卡**，**面板首次全勤**（84 票零漏投零中斷） | [SUMMARY](../FR-081-2609-issue-tracking-security-scan/SUMMARY.md) |
| **舊 arc（2026-07）** | 主專案 BE／FE | Sonar／Semgrep／Trivy | ✅ 已收官（v1.10.1 清理完成） | [索引](../security-scan-2607/) |

**面板狀態決定可信度，三種「掃完」不一樣**：

- ✅ **面板完整跑完且有實質票數**——**FR-081 六棒是至今唯一全勤的 arc**（84 票全投、零漏投、零中斷）。關鍵不在檔數而在**分開跑**：六棒一次都沒撞額度，對照 FR-079 B2 撞兩次、跑 14 小時。
- ✅ **FR-082 jedi-ai-bot（A1，14 檔，2026-09-10）**——stamp `verified` 且**無拒收原因，七個 arc 以來最乾淨的一次**；9 票全投零漏投。1 條 MEDIUM（[CM-1638](https://app.notion.com/p/FR-082-A-AI-AI-3d7346da4cd081658b9bc6f74d5b6af6)）：**聊天端點無長度與次數上限，4～8 個並發請求即可佔滿全部工作程序讓整個產品停止回應**，或無限次呼叫燒光全公司共用的 AI 額度。[報告](../FR-082-2609-ai-bot-security-scan/scan-A1-ai-bot.md)
- ✅ **FR-083 jedi-ai-dashboard D2（宿主接線，18 檔，2026-09-10）**——stamp `verified`、**33 票全投零漏投**、面板主動降級 2 條。**11 條（2 HIGH／9 MEDIUM）**：範圍內 3 條全與「AI 儀表板繞過權限檢查」有關（[F3 全公司帳號名冊](../FR-083-2609-ai-dashboard-security-scan/scan-D2-host-wiring.md)／F9 回應夾帶密碼鹽值／F10 專案清單 `is_admin=True` 後門**且為刻意設計**）；範圍外 8 條是密鑰專項順手撈到，**其中 F1（GitLab 權杖）與 F2（Nexus 管理員帳密＋MinIO 金鑰）是新的**。⚠️ **卡片點名的「27 支 API 權限形狀表」工具只做了 5 支**，其餘待人補。**D1（套件本體 34 檔）尚未跑。**
- ⚠️ **工具零發現 ≠ 乾淨**——FR-081 的 I3／I4／I6 三棒工具在範圍內都是 0 條，**那三棒真正的產出全是首腦補查的**（含「六張表零 RLS」）。小範圍的棒次尤其明顯。
- ⚠️ 下面兩棒要打折看：

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

---

## 2. 修正卡總表（40 張）

### 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（16 張）— **這是「還有哪些要修」的核心**

按嚴重度排序。**全部未動是決策者裁定「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-1629** | **DB 管理員密碼（與 Redis 同一組）被寫進 249 個檔**，其中一份把主機／帳號／密碼湊在相鄰兩行，可直接使用。該帳號 **BYPASSRLS**，且同一把用在 DEV、**出貨基線庫**與 STG／POC（POC 依規定等同正式環境） | 🟠 **HIGH** | FR-081 I2 |
| **CM-1630** | **意見回饋六個功能只有「匯出」檢查權限**，其餘五個任何登入者都能用；改／刪從不檢查那筆是不是你的，稽核紀錄還把他記成合法操作人。**唯一「普通員工現在就能用」的一條** | MEDIUM | FR-081 I2 |
| **CM-1631** | **Google 雲端硬碟應用程式密鑰與加密金鑰外洩**（22 檔）。**這把不是每套安裝各自產生的**，是 Google 後台一組、所有環境共用——外洩比 JWT 金鑰那條更實在 | MEDIUM | FR-081 I2 |
| **CM-1632** | 連 GitHub 兩處 `verify=False`——**帶著存取權杖走不驗憑證的 TLS**（本專案同款病第四處） | MEDIUM | FR-081 I1 |
| **CM-1634** | **Nexus 私有套件庫走明文連線**且是主要來源（26 個專案全一樣）。內網有心人可在安裝時掉包，**而打包機產出的是客戶拿到的安裝檔**——供應鏈的根 | MEDIUM | FR-081 I5 |
| **CM-1633** | 刪除附件安全檢查只做一半（算了過濾結果卻沒用）。目前打不到，未來做批次刪除會**靜默刪錯檔** | LOW | FR-081 I3 |
| **CM-1559** | **RLS fail-open**（`session_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 進入點）」。

| **CM-1638** | **AI 聊天端點無長度與次數上限**。任一登入者開 4～8 個並發請求即可佔滿全部工作程序，**整個產品所有功能停止回應**；或無限次呼叫燒光全公司共用的 AI 額度 | MEDIUM | FR-082 A1 F1（2026-09-10）|

### 2.3 ⏸ 暫緩（1 張）

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

---

## 3. 🔴 掃出來但**還沒開卡**的（16 項）

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

### 🔴 要開卡時不用重掃（2026-09-10 實測驗證）

決策者問過「這些過陣子還知道怎麼開卡嗎？該不會要重掃吧」。**不用。** 每項的「**開卡素材**」欄標明成本：

| 標記 | 意思 | 成本 |
|---|---|---|
| ✅ | **報告裡有 `檔:行號` ＋ 具體修法**，直接抄 | 幾分鐘 |
| ⚠️ | 報告只有結論，**要補查程式碼但不用重掃**（欄內已寫要查什麼） | 十分鐘內 |

**為什麼 ⚠️ 類也不用重掃**：那些是「工具讀過但判定為刻意設計所以沒報」的，**事實還在原地，grep 就回來了**。2026-09-10 實測第 6 項（最舊的一條，FR-076，兩週前）：報告只有一句「DEV 私鑰簽的照 POC 也認」，**兩個指令、不到五分鐘就補回完整位置與結構**。

**真正需要重掃的只有「當時根本沒讀到那個檔」**——那類單獨列在 §3.4「等於沒查」，不混進這裡。

### 3.1 資安類（10 項）

| # | 內容 | 嚴重度 | 出處 | 開卡素材 |
|---|---|---|---|---|
| 1 | **公告授權補強四合一**：AI 儀表板旁路可讀全租戶公告（含草稿，且前三筆原文送第三方 LLM）／改刪公告不驗歸屬且靜默清空發送對象／單筆讀取零檢查／列表對無部門帳號直接全放行 | MEDIUM×2＋LOW×2 | FR-079 B2 F13/F16/F17/F18  ✅ `bulletin_route.py:29/46/55`、`bulletin_service.py:79/111/119/162/165/180`，修法在報告各條 |
| 2 | **憑證輪替與清除**：`cmmgr` DB 密碼（`BYPASSRLS`）／四家 LLM API 金鑰（9 檔）／Nexus＋MinIO 憑證（**供應鏈的根**）／migration 腳本把真密碼當環境變數 default | MEDIUM×4 | FR-079 B2 F1/F2/F3/F14  ✅ 報告有 9 個精確位置（含 `docs/analysis/2026-05-28-poc-db-migration-plan.md:73`）＋ CM-1629 已寫治本三步 |
| 3 | **installer 每套部署種同一組原廠 super admin 密碼**，bcrypt hash 寫死在 SQL、不強制首次改密 | MEDIUM | FR-079 B2 F15（**決策者裁：先記錄，之後看怎麼調整**）  ✅ `scripts/init/06-admin.sql:41-42`（hash）／`:69-82`（寫入） |
| 4 | **`bulletin_org_units` RLS 未設**（走 sql-migration SOP） | — | FR-079 B2 重點⑩  ✅ 報告已列 `bulletins` 四支 policy 對照（該表有、`bulletin_org_units` 零）；走 sql-migration SOP |
| 5 | **三張表有 RLS policy 但 RLS 沒啟用**：`compliance.projects`／`workflow_executions`／`workflow_templates`，且 `projects` 的 policy **沒有 super admin 分支**。現在不會出事（policy 沒生效），**哪天有人打開 RLS 會直接壞** | 定時炸彈 | CM-1559 盤點順帶發現  ⚠️ **要補查**：三張表名已知（`compliance.projects`／`workflow_executions`／`workflow_templates`），但 policy 內容與缺 super admin 分支的確切位置要 grep `scripts/init/02-schema.sql` 補 |
| 6 | **三環境硬編公鑰**：DEV 私鑰簽的照 POC 也認。決策者已裁「現階段不急，綁正式 LC 一併處理」，但**尚未落成卡** | 綁正式 LC | FR-076 L1  ✅ **2026-09-10 已補查**：`jedi-license-runtime/jedi_license_runtime/common/public_keys.py`（27 行）的 `PUBLIC_KEYS` 三筆並列 DEV(`kid` 2ce3bb59…)／STG(04b1e65f…)／POC(f3b562a6…)，**三環境公鑰全部編譯進同一份後端**，驗章按 kid 查表 → DEV 私鑰簽的照 POC 也認。檔頭註解自陳「編譯進程式、不放設定檔」是刻意設計（為支援金鑰輪替）→ **與 FR-083 F10 同型：要先做產品決策再改碼** |
| 7 | **jedi-issue 六張表完全沒有客戶隔離**：`issues`／`labels`／`members` 與三張 mapping 表**零 RLS 零 policy，連「這是哪個客戶的」欄位都沒有**（主專案自建的 `feedback_issues` 有 4 條 policy，對比鮮明）。**比 FR-079 那條更徹底**——那張至少有欄位、補規則就好，這六張要補得先改表結構。目前實際影響有限（`project_name` 寫死 "CM"、全租戶共用一份平台設定），但**資料庫層對這六張表沒有任何第二道防線**，配合 CM-1630 的「改／刪不驗歸屬」等於無兜底 | 低／設計註記（首腦判） | FR-081 I6（**首腦補查，工具零發現**；已併入 CM-1630 背景說明，**未獨立開卡**） ✅ 報告有七張表的隔離狀態對照表（六張零 RLS vs `feedback_issues` 四條 policy） |
| 8 | 🔴 **AI 儀表板讓任何登入者列出全公司帳號／角色／租戶／部門**。同一個 `UserService.get_users`：走正常網頁路徑要 `@capability_required("user.read")`（`jedi_iam/api/routes/user_route.py:80`），**走 AI 儀表板完全不檢查**（`di_containers/dashboard_apis/auth.py:31`，另 `:19`／`:43`／`:55` 同款）。產品自己定義了 `user.read`／`role.read`／`tenant.read`／`department.read` 四個權限點，**這條路四個全繞過**。攻擊只需一個普通帳號＋一句 prompt。**修法**：正解是讓 27 支申報 API 各自帶上所需權限、`DataAPIService` 派發前檢查；最小修法是把 auth 四支從申報檔移除或改指向只回摘要的方法 | MEDIUM | FR-083 D2 F3（**決策者裁：先不開卡，之後從總表決定**） ✅ `dashboard_apis/auth.py:19/31/43/55`、對照組 `jedi_iam/api/routes/user_route.py:80`，修法（正解＋最小修法）在本列 |
| 9 | **AI 儀表板回應夾帶每個帳號的密碼鹽值**。`UserDTO` 本身帶 `salt` 欄位（`jedi_iam/app/dto/user.py:43`，`:98` 填值），而正常列表回應 `UserPageQueryResponse` **刻意排除 salt/password**——唯獨儀表板這條路沒做欄位過濾，整個物件序列化後送進回應。前端只顯示幾欄是顯示行為，**後端已經送出去了**。**修法**：加欄位白名單，或重用既有序列化器 exclude；更根本是「帶憑證欄位的 DTO 不該進通用序列化路徑」 | MEDIUM | FR-083 D2 F9（同上） ✅ `jedi_iam/app/dto/user.py:43`（欄位）／`:98`（填值）、`dashboard_apis/auth.py:15`（宣告），修法在本列 |
| 10 | **AI 儀表板專案清單有 `is_admin=True` 後門**，非成員可列舉租戶內全部專案（`di_containers/dashboard_apis/project.py:52` → `app/flow_control/service/project_service.py:222`）。🔴 **這是刻意設計不是寫錯**——該方法 docstring 自陳「對齊 v1 dashboard 看本 tenant 全部專案 → `is_admin=True` 繞 grc user 參與可見性，tenant 隔離由 RLS 負責」。**真正的問題是那個決定在「使用者打字、AI 自己決定查什麼」的新情境下沒有人重新檢視過**。**修法要先做產品決策再改碼**，直接拿掉可能弄壞既有行為 | MEDIUM | FR-083 D2 F10（同上） ✅ `dashboard_apis/project.py:52` → `app/flow_control/service/project_service.py:222`，且 docstring 自陳理由（已引在本列） |

### 3.2 非資安但是真 bug（4 項）

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

**四項的開卡素材全部 ✅**——位置欄本身就是 `檔:行號`，四條都是「一兩行的修正」，開卡時直接抄。

| # | 內容 | 位置 |
|---|---|---|
| 7 | `PUT /tenant/<uid>` 與 `PUT /org-unit/<uid>` 部分更新會**把 `parent_id` 打成 NULL**，留下 `parent_id` 與 `path` 互相矛盾的資料列 | `tenant_repo_impl.py:44`／`org_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 項）

**這兩項的 Notion 卡已經存在**（CM-1556／CM-1599），不需要「開卡」，只需要**發令派工**。

| # | 內容 |
|---|---|
| 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 查渲染方式，FR-079 B2 未查。
- **審計欄位 subquery 是否繞過 `users` 表 RLS**——FR-079 B2 未查。
- **`docs/`、`scripts/` 兩棵樹從來不是掃描目標**——多條金鑰外洩是密鑰專項順手撈到的，**「範圍外」的發現不代表那些地方被檢查過**（FR-078 N2 與 FR-081 皆明載）。
- **FR-081 六棒的逐檔閱讀帳本都是空的**——無法證明每個檔都被讀到結論。六件事都是真的，但「jedi-issue 只有這六個問題」不成立。
- 🔴 **AI 儀表板的 27 支申報 API，只查了 5 支**（FR-083 D2）。卡片明寫「逐支確認權限形狀」是本 arc 最有價值的產出，**工具實際只碰了 auth 4 支＋project 1 支**。**未查的 22 支不能當作乾淨**——尤其 `participant` 那 7 支（「你在這個專案能幹嘛」的資料源，風險僅次於 auth）、`flow_engine` 3 支、`oscal`／`survey` 各 2 支。**建議在 D1 驗收時由人補完這張表。**

---

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

**25 支 jedi-* 套件，實質掃過 7 支。** 未掃合計約 **100 棒、120 小時**（純掃描，不含驗收／開卡／修正）。

| 狀態 | 套件 |
|---|---|
| ✅ 掃完 | jedi-iam（S7 待重跑）、jedi-license-runtime、jedi-notification、jedi-bulletin、**jedi-issue**（六棒全勤，2026-09-10）、**jedi-ai-bot**（一棒，2026-09-10）|
| 🔄 部分 | jedi-remote-agent（R1 完成、餘暫停）、jedi-detection（僅 agent 相關 11 檔，**餘 140 檔未掃**）、**jedi-ai-dashboard**（D2 宿主 18 檔已掃，**D1 套件 34 檔未掃**）|
| ⚠️ **不算數** | **jedi-common**——只有第一輪未經面板的半途掃描 |
| ⬜ 完全沒碰 | 其餘 16 支 |

**🔴 下一支已定：jedi-ai-dashboard**（決策者 2026-09-10 指定，FR-083 兩棒）——**排名表把它列在「讀取展示型、攻擊面小」，但那個評估同樣只看了套件本體**。實際盤點：套件 33 檔 ＋ **BE 宿主接線 18 檔**，而宿主那半邊有 `di_containers/dashboard_apis/` 的 **14 支申報檔、合計申報 27 支 API**（participant 7 支、auth 4 支為大宗）。**FR-079 的 F13 已證明那條路不經 route 層守門、且結果前三筆原文送第三方 LLM——當時只驗證了 27 支裡的 1 支（公告）。** 故切兩棒：D1 套件本體 33 檔（jedi monorepo）／D2 宿主接線與 API 名冊 18 檔（**BE repo**），**建議 D2 先跑**。

**首腦建議的再下一批順序**（按風險，不是按檔數）：

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 檔裡**，十個重點有八個落在宿主側。**排下一支時要先問「這支有沒有宿主那一半」。** FR-081 的宿主那半藏在 `feedback/` 底下，**用檔名 grep `issue` 會漏掉**。
3. **切棒尺放寬為 40 檔，但前提是一次只跑一棒**（FR-081 換來）——FR-077 R1 的 42 檔曾讓 105 個 verifier 全滅，據此把尺收到 30；FR-081 I5 故意放到 40 檔，15 票全投零中斷。**差別不在檔數，在有沒有和別的工作搶額度。** 六棒全部分開跑一次都沒撞額度，對照 FR-079 B2 撞兩次、跑 14 小時。
4. **套件自己的註解會騙人**——FR-081 開卡前查證，套件檔頭自稱「GitLab／GitHub 整合沒在用、約佔 58%」是**錯的**（主專案六處實際呼叫）。照它跳過就會漏掉唯一會帶著密碼對外連線的那半邊。這是工具已知盲點「被程式碼註解說服」的現行犯。

---

## 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. 等決策者裁的事項（8 項）

**掃描本身**：

1. **下一支掃哪個套件**——FR-081 已完成，首腦建議 **jedi-common**（地基，至今無算數掃描）或 **jedi-integrity**（CP 值最高）。
2. **S7 重跑時機**——已裁要重跑，未排。

**憑證處置（FR-081 帶出，三件都要裁）**：

3. **DB／Redis 密碼要不要換？**（CM-1629）依 FR-079 判準查過安裝程式，**每套安裝各自產生、客戶端是安全的**——但**這條不能因此降級**：同一把用在 DEV、**出貨基線庫**與 STG／POC，而 POC 依規定等同正式環境、基線庫是出貨映像檔的來源。**與「只影響開發機」的 JWT 金鑰那條不同。** 若要換，DEV 與基線庫可規劃；**STG／POC 屬環境異動，依鐵律要決策者當次明示。** 另建議把 Redis 與 DB 密碼**分成兩組**（目前同一組）。
4. **Google 應用程式密鑰要不要現在轉？**（CM-1631）**這把不是每套安裝各自產生的**，是 Google 後台一組、所有環境共用，轉了要重發到各環境。加密金鑰若要換，**得先寫好「把既有權杖重新加密」的程式**，否則客戶既有的雲端硬碟整合會全部失效。
5. **Nexus 上 jedi_issue 0.0.14／0.0.15 兩個舊套件檔下架了沒？**——CM-1573 沒收乾淨的尾巴（那兩版把含密碼的設定檔打包進去發布）。**程式碼查不到，要連 Nexus 才能確認。**

**其他**：

6. **CM-1559 修法方向**——盤點已完整回寫 Notion 卡，等裁「先下第二刀再下第一刀」這個順序可不可以、以及三類分流的範圍。
7. **上版時機**——jedi-iam 13 張 Done 修正卡何時與 LC 一起發版上 STG/POC。
8. **CI 加秘密掃描**（gitleaks／trufflehog 擋在 pre-commit 或 CI）——新增基礎設施要決策者裁。**FR-081 的 249 檔事件讓這件事更急**：憑證被工作過程寫進版控已是第三次（`.env.test`／JWT 金鑰／DB 密碼），九成來自查資料庫的指令被寫進對話紀錄。**不改工作方式，清了還會再長出來。**

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

---

## 7. 座標

**六個 arc 各自的站**（本表只做收斂，逐條技術細節在各站）：

| Arc | 掃什麼 | 站 |
|---|---|---|
| FR-075 | jedi-iam | [`FR-075-2609-jedi-package-security-audit/`](../FR-075-2609-jedi-package-security-audit/README.html) |
| FR-076 | License 簽發與驗證鏈 | [`FR-076-2609-license-chain-security-scan/`](../FR-076-2609-license-chain-security-scan/README.html) |
| FR-077 | 遠端 Agent 控制鏈（⏸ 暫停） | [`FR-077-2609-remote-agent-security-scan/`](../FR-077-2609-remote-agent-security-scan/README.html) |
| FR-078 | jedi-notification | [`FR-078-2609-notification-security-scan/`](../FR-078-2609-notification-security-scan/README.html) |
| FR-079 | jedi-bulletin | [`FR-079-2609-bulletin-security-scan/`](../FR-079-2609-bulletin-security-scan/README.html) |
| FR-081 | jedi-issue | [`FR-081-2609-issue-tracking-security-scan/`](../FR-081-2609-issue-tracking-security-scan/README.html) |
| 舊 arc | 主專案 BE／FE（2026-07） | [`security-scan-2607/`](../security-scan-2607/README.html) |

**其他座標**：

| 要什麼 | 去哪 |
|---|---|
| 現況與派工紀律（living） | [`FR-075/handoff/security-scan-STATE.md`](../FR-075-2609-jedi-package-security-audit/handoff/security-scan-STATE.md) |
| 歷程（append-only） | [`FR-075/handoff/security-scan-LOG.md`](../FR-075-2609-jedi-package-security-audit/handoff/security-scan-LOG.md) |
| 首腦手冊（切棒／開卡／驗收／裁決） | `.claude/skills/security-scan-lead/SKILL.md` |
| 工具用法與失敗紀錄 | [`FR-075/scan-methodology.md`](../FR-075-2609-jedi-package-security-audit/scan-methodology.md) |
| 2026-07 工具掃描原始產物 | `docs/security-reports/2026-07-24|25/` |
| 建卡腳本 | `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。

---

> **維護紀律**：本表由掃描首腦在**每一棒驗收完成時**同步更新，與回寫母卡同一個動作（`security-scan-lead` skill 第五節第 7 步「回寫四處」與 5.1 節）。**不要累積到 arc 結束才補**——2026-09-09 建好後隔天就因 FR-081 收口而 stale，而 stale 的總表比沒有更糟。
