FR-081 · 需求索引 · 本頁由 build 掃資料夾生成
第六個資安掃描 arc,目標是「問題追蹤」這條鏈。 六棒都已開卡、尚未啟動。決策者裁一次只派一棒。
使用者在系統裡送「意見回饋」,系統會把它變成一張問題單。這張單子可以只存在本地,也可以同時拿公司的權杖去 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 | ⬜ Not started | — | — |
| 2 | I2 宿主接線 | CM-1614 | ⬜ Not started | — | — |
| 3 | I3 附件上傳下載 | CM-1615 | ⬜ Not started | — | — |
| 4 | I4 對外面與插件契約 | CM-1616 | ⬜ Not started | — | — |
| 5 | I5 app 與 domain 層 | CM-1617 | ⬜ Not started | — | — |
| 6 | I6 持久層 | CM-1618 | ⬜ Not started | — | — |
(尚無——六棒都還沒跑。依決策者 2026-09-08 裁定,掃描結果產生的修正卡一律先不派,由 PM 收集所有掃描結果後統一安排。)
.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,不要切卡片內容(決策紀錄、驗收條件)以 Notion 為準,本頁只記座標。
| 關係 | 卡號 | 標題 | 狀態 |
|---|---|---|---|
| 母案 | CM-1612 | FR-081 jedi-issue 問題追蹤鏈資安掃描(六棒,只掃不修) | — |
| 子卡 | CM-1613 | I1 第三方整合與憑證(25 檔) | Not started |
| 子卡 | CM-1614 | I2 宿主接線(31 檔,BE repo) | Not started |
| 子卡 | CM-1615 | I3 附件上傳下載(14 檔) | Not started |
| 子卡 | CM-1616 | I4 對外面與插件契約(20 檔) | Not started |
| 子卡 | CM-1617 | I5 app 與 domain 層(40 檔) | Not started |
| 子卡 | CM-1618 | I6 持久層(28 檔) | Not started |