FR-081 · 需求索引 · 本頁由 build 掃資料夾生成
✅ 六棒全數掃完並經首腦驗收(2026-09-10);發現已全數處理——7 條(總表 M23-1~7)全部已修(1.21.0 出貨:CM-2049/FR-114.1-7/CM-2051/CM-2066/鎖定檔入版控/CM-2230+CM-2252);原 CM-1629~1634 六張早期卡已作廢,改照內化版問題總表派工。總結報告見 SUMMARY.md
這是六個資安掃描 arc 之一。 六個 arc 合起來的結論、修正卡狀態、還沒開卡的待辦與覆蓋率地圖,在跨 arc 總表:
security-scan-consolidated/——要問「總共掃出什麼、還有哪些要修」看那份,本頁只講這一支。
第六個資安掃描 arc,目標是「問題追蹤」這條鏈。 六棒已全部掃完並驗收(2026-09-10,當時裁一次只派一棒);發現已全數處理,見下方修正卡段。
使用者在系統裡送「意見回饋」,系統會把它變成一張問題單。這張單子可以只存在本地,也可以同時拿公司的權杖去 GitLab 或 GitHub 開一張真的 issue,還會把使用者上傳的附件一起送過去。
要檢查的是:使用者打的字與上傳的檔,一路流到第三方服務的過程中會不會出事——權杖會不會外洩、檔案會不會被放到不該放的地方、有沒有人能看到不該看的東西。
jedi_issue/api/__init__.py:11-13 白紙黑字寫「GitLab/GitHub 整合目前產品沒有在用,約佔套件 58%」。
首腦從宿主端查證,是錯的:app/feedback/service/feedback_service.py 的 156/171/210/222/246/252 六處實際呼叫 create_gitlab_issue/create_github_issue/update_*/set_*_issue_closed,由 _is_gitlab_enable()/_is_github_enable() 開關控制。IssueProviderCode 使用統計:LOCAL 9 次、GITLAB 4 次、GITHUB 3 次。
這正是工具已知盲點二(會被程式碼註解說服)的教科書形狀——研究員讀到那段 docstring 就會跳過 58% 的程式碼,而那半邊恰好是風險最高的(外部連線+憑證)。FR-075 的 S2 就是這樣八檔零發現卻漏掉真洞。六張子卡每張都帶了這個警告。
# jedi_issue/infra/github.py:22
return Github(auth=auth, per_page=100, timeout=10, verify=False)
# jedi_issue/infra/issue/adapter/github/github_issue_adapter.py:43 同一行帶著存取權杖走不驗憑證的 TLS,中間人可直接攔下 token。token 來自 os.getenv("GITHUB_PRIVATE_TOKEN")(github.py:16)。
更該注意的是前科:CM-1573 就是「jedi-issue PAT 外洩處置」——這個模組的權杖外洩過一次。現在同一個模組還在用 verify=False 傳它。首腦初判 HIGH,交由 I1 棒的面板驗證。
(本專案這是同款病第四處:CM-1560 LDAP TLS、CM-1565 Redis TLS、CM-1606 SMTP starttls。)
feedback/ 底下,用檔名 grep issue 會漏掉BE 側真正的攻擊面是「使用者送意見回饋 → 系統拿公司 PAT 去第三方開 issue 並夾帶使用者上傳的檔案」,程式碼在 api/feedback/、app/feedback/、domain/feedback/、infra/feedback/。
這是 FR-079 換來的教訓的直接應用——排名表的檔數只算套件本身,不含宿主接線;排任何一支之前要先問「這支有沒有宿主那一半」。
| 順序 | 卡 | 棒 | 檔數 | scanRoot | 為什麼獨立 |
|---|---|---|---|---|---|
| 1 | CM-1613 | I1 第三方整合與憑證 | 25 | jedi | 🔴 風險最高:憑證+外部連線+外洩前科三者疊加 |
| 2 | CM-1614 | I2 宿主接線 | 31 | BE | scanRoot 不同;使用者輸入與守門都在這 |
| 3 | CM-1615 | I3 附件上傳下載 | 14 | jedi | 三種後端各自實作,一份漏做就是洞 |
| 4 | CM-1616 | I4 對外面與插件契約 | 20 | jedi | 唯一一條 route 吐成員名冊且只有 @jwt_required() |
| 5 | CM-1617 | I5 app 與 domain 層 | 40 ⚠️ | jedi | 授權判定;邊界測試,見下 |
| 6 | CM-1618 | I6 持久層 | 28 | jedi | 租戶隔離的最後防線 |
合計 158 檔(套件 127 + 宿主 31)。按實測每棒約 70 分鐘算,約 7 小時純掃描。
issue_plugin_wiring.py。兩棒都要驗,不要互相假設對方驗過了。local_issue_attachment.py:63 有就地 IssueUploadFilesRepoImpl()。每棒 ≤30 檔是實測邊界(FR-078 的 30/18 檔跑完、FR-077 的 42 檔全滅)。I5 的 40 檔刻意略超——app/ 與 domain/ 拆開會把「用例編排」與「業務規則」切在接縫上,而權限漏洞正活在那裡。40 檔中 18 個是空的或極短的 __init__.py,實質約 22 檔。
若面板未完整跑完 → 不要重跑整棒,回報首腦決定是否拆成 app/(22)+domain/(18)。這一輪的數字會決定往後 30~40 檔區間的切棒尺。
I1+I2+I3 共 70 檔,涵蓋絕大部分風險面(憑證、輸入流、檔案)。若額度吃緊可在此收一輪。但沒跑完六棒就不能宣稱「jedi-issue 掃過了」——I6 卡已要求報告回答這個母卡層級的問題。
low + focus attack-surface(附帶密鑰專項,是免費收益)save_result.py 遇同 shard 會靜默擇一、不報錯)| 順序 | 棒 | 卡 | 檔 | 面板 | 範圍內淨新增 | 報告 |
|---|---|---|---|---|---|---|
| 1 | I1 第三方整合與憑證 | CM-1613 | 25 | ✅ 9 票全投 | 2 | 報告 |
| 2 | I2 宿主接線(BE) | CM-1614 | 31 | ✅ 30 票、verified |
5(含唯一 HIGH) | 報告 |
| 3 | I3 附件上傳下載 | CM-1615 | 14 | ✅ 9 票全投 | 0 +首腦補 1 | 報告 |
| 4 | I4 對外面與插件契約 | CM-1616 | 20 | ✅ 12 票全投 | 0(兩項查證首腦補做) | 報告 |
| 5 | I5 app 與 domain | CM-1617 | 40 | ✅ 15 票全投 | 1(明文套件庫) | 報告 |
| 6 | I6 持久層 | CM-1618 | 28 | ✅ 9 票全投 | 0 +首腦查出六表無 RLS | 報告 |
六棒面板全部完整跑完、零漏投、零不完整、一次都沒撞額度——這是本專案六個掃描 arc 以來第一次。
總結報告:SUMMARY.md — 決策者要看的那份,開頭一句話回答「要修幾條」。
| 卡號 | 修什麼 | 嚴重度 | 建議順序 |
|---|---|---|---|
| CM-1629 | 資料庫+Redis 密碼散在 249 個版控文件(含 POC 完整連線字串)+堵住再發生的路 | 🔴 HIGH | 1 |
| CM-1630 | 意見回饋六條端點只有匯出掛守門;改/刪不驗歸屬 | 🟡 MEDIUM | 2 |
| CM-1631 | Google Drive OAuth 密鑰與 Fernet 金鑰外洩(需 Google 主控台重設) | 🟡 MEDIUM | 3 |
| CM-1632 | 連 GitHub 關閉 TLS 憑證驗證(兩處) | 🟡 MEDIUM | 4 |
| CM-1634 | 內部套件庫走明文 HTTP 且為主要來源(26 個 repo) | 🟡 MEDIUM | 5 |
| CM-1633 | 附件刪除守門只用了一半 | ⚪ LOW | 6 |
另有 3 條(JWT/Turnstile 金鑰、舊套件 .env)併入既有的 CM-1607,不另開卡。
現況:六張早期卡已作廢,問題改照內化版問題總表(docs/security-report/M23-issue.md)派工,全數已修(1.21.0 出貨):CM-1629→CM-2049(249 檔殘留字串已清,密碼換發排在正式環境上版前)、CM-1630→FR-114.1-7、CM-1631→CM-2051、CM-1632/1633→CM-2066、CM-1634→版本鎖定檔入版控(連線維持 http,決策者裁倉庫與打包機都在內網)。另 3 條併入的 CM-1607 衛生項亦已清(CM-2048)。
.claude/skills/security-scan-lead/SKILL.mddocs/features/FR-075-2609-jedi-package-security-audit/handoff/security-scan-STATE.mded62d8a)——同一模組的權杖外洩前科../FR-079-2609-bulletin-security-scan/scan-B2-host-wiring.mdfeature/FR-075,不要切2026-09-16 起本 FR 的後續在 FR-101:FR-099 把主專案的意見回饋與標籤整組搬進套件後,本頁 I2 掃的 31 檔主專案側已全部刪除,CM-1630 等發現的新落點在套件裡;套件 151 檔中有變動的 93 支由 FR-101 三棒重掃,未變動的 57 支沿用本頁六份報告的結論。
以下全部由 build 掃資料夾產生,新增檔案重 build 即自動出現。標題連結指向渲染後的 HTML,md 連向源檔。
| 文件 | 類型 | 標題 | 最後更新 |
|---|---|---|---|
| scan-I4-plugin-contract / md | API 規格 | I4 檢查結果:對外的 API 與插件裝配 | 2026-09-10 |
| 文件 | 類型 | 標題 | 最後更新 |
|---|---|---|---|
| scan-I1-third-party-integration / md | 盤點證據 | I1 檢查結果:跟 GitHub/GitLab 連線的部分 | 2026-09-10 |
| scan-I2-host-wiring / md | 盤點證據 | I2 檢查結果:主專案的「意見回饋」功能 | 2026-09-10 |
| scan-I3-attachments / md | 盤點證據 | I3 檢查結果:附件上傳下載 | 2026-09-10 |
| scan-I5-app-domain / md | 盤點證據 | I5 檢查結果:業務邏輯層 | 2026-09-10 |
| scan-I6-persistence / md | 盤點證據 | I6 檢查結果:資料存取層 | 2026-09-10 |
卡片內容(決策紀錄、驗收條件)以 Notion 為準,本頁只記座標。