檢查日期 2026-09-09~10|耗時 105 分鐘|對應卡片 CM-1618|FR-081 最後一棒
工具在這 28 個檔裡沒找到問題,但首腦補查發現:這個套件建的六張資料表,完全沒有「每個客戶只能看自己資料」的隔離機制——連用來分辨客戶的欄位都沒有。
問題單的資料怎麼存進資料庫、怎麼查出來——28 個檔案。
為什麼「預期產出低」還是要檢查:客戶資料隔離的最後一道防線就在這一層。FR-079 那次也是在同樣「預期低產出」的地方,查出一張表完全沒有隔離設定。
工具找到的兩條都不在資料存取層,是研究員追到範圍外的舊問題:
| # | 位置 | 狀態 |
|---|---|---|
| 1 | github_issue_adapter.py:43 |
第六次被撈到,重複 |
| 2 | jedi_issue/.env |
重複(CM-1573 舊案) |
工具在這 28 個檔裡找到的新問題:0 個。
白話:資料庫有一個機制叫 RLS(Row Level Security),作用是「每個客戶只能看到自己的資料」——就算程式寫錯了,資料庫這一層也會擋住。這是最後一道防線。
首腦逐張表去查出貨用的資料庫結構檔:
| 資料表 | 有開客戶隔離嗎 | 隔離規則幾條 | 有「這是哪個客戶的」欄位嗎 |
|---|---|---|---|
issues(問題單) |
❌ 沒有 | 0 | ❌ 沒有 |
labels(標籤) |
❌ 沒有 | 0 | ❌ 沒有 |
members(成員) |
❌ 沒有 | 0 | ❌ 沒有 |
issue_assignee_mapping |
❌ 沒有 | 0 | ❌ 沒有 |
issue_label_mapping |
❌ 沒有 | 0 | ❌ 沒有 |
issue_upload_file_mapping |
❌ 沒有 | 0 | ❌ 沒有 |
**feedback_issues(主專案自己建的) |
✅ 有** | 4 | ✅ 有 |
對比非常清楚:主專案自己建的那張表,隔離機制完整;套件建的六張表,一張都沒有。
這比 FR-079 查到的更徹底:那次那張表至少還有「這是哪個客戶的」欄位,只是沒設隔離規則——補上規則就好。這六張連欄位都沒有,要補隔離得先改資料表結構。
首腦追了主專案怎麼用它:
# app/feedback/service/issue_service.py 第 41 行
self.project_name = "CM" # 寫死
# 第 46 行的註解:任一租戶建 feedback issue 都走這份平台設定目前所有客戶的意見回饋都寫進同一個「平台專案」,本來就是共用的,不是「應該隔離卻沒隔離」。真正帶客戶身分的是主專案那張 feedback_issues 表(有隔離),使用者看到的清單經過它。
所以現在不是可以被利用的漏洞。但有兩件事要記住:
feedback_issues 的隔離是唯一屏障。配合 I2 查到的「改/刪不檢查歸屬」,沒有兜底。處置:判「低/設計註記」,併入 CM-1630 的背景說明,不另開卡。
# jedi_issue/common/utils/common_util.py
def generate_uuid():
return str(uuid.uuid4())用的是 uuid4,是密碼學等級的隨機,猜不到。 與 FR-079 那次的結論一致。
這件事重要,是因為如果編號可以猜,那些「只靠編號就能存取」的功能風險就會放大。現在確認猜不到,那些功能的風險維持在原本判定的等級。
卡片的檢查範圍寫了一個不存在的路徑(jedi_issue/infra/issue/mapper/)。實際上 mapper 相關檔案都在 label/ 和 member/ 底下,已經被其他路徑涵蓋了。
工具照實指出了這件事。檔案數 28 仍然對得上、沒有漏檢查,但這是開卡時應該用指令逐條驗證卻沒做到位的地方。記錄下來給後面的棒次參考。
兩條都是 3 票全過,9 票全數投出、零漏投。首腦補查的隔離結論,是逐張表去核對出貨用的資料庫結構檔得出的。
報告自己寫了一句很誠實的話:「快篩模式下的『沒發現問題』,比徹底檢查後的『沒發現問題』證據力弱」。
而首腦補查證明了:工具的「沒發現問題」確實漏掉了東西——那六張表沒有客戶隔離。
為什麼工具看不到:因為那不是「程式碼寫錯了」,是「資料表結構少了東西」。研究員讀的是程式碼,資料庫結構不在他們的視野裡。
這是給後面棒次的重點:資料庫層的問題要靠人主動去查資料表結構,不能等工具報。
| 項目 | 數字 |
|---|---|
| 檢查範圍 | 28 個檔案 |
| 派出/回報的研究員 | 2 / 2 |
| 候選問題 → 去除重複 | 3 → 3 |
| 投票數 | 9 |
| 沒投到票的 | 0 |
| 範圍內新問題(工具) | 0 |
| 首腦補查項目 | 2(其中一項是新發現) |
| 耗時 | 105 分鐘 |