FR-098 · 需求索引 · 本頁由 build 掃資料夾生成
✅ 兩棒掃完並驗收收尾(2026-09-16);發現已全數處理——M19 三件全數已修,隨 1.21.0 出貨(母卡 CM-1813、子卡 CM-1814~1815)。套件本體 60 檔掃完(A1 設備 45 檔+A2 資訊系統 42 檔,共用骨架 27 檔重疊);淨新增 2 條:跨 arc 總表第 80 項(中等,讀取端點不驗權限=產品決策題,設備與資訊系統兩張清冊同一決定)、第 81 項(低,只有修改權限也能達成刪除)。沒有高風險,資料庫隔離做得好。主專案宿主接線 12 支另棒(與 jedi-log 根層 6 支合併,BE repo)。
兩棒都掃完、都驗收了。整支套件 3 條實質發現,沒有高風險,資料庫隔離做得好。
| # | 發現 | 嚴重度 | 歸屬 |
|---|---|---|---|
| 1 | 設備與資訊系統的讀取端點只驗登入、不驗權限——程式碼裡寫明是刻意取捨 | 中等 | 跨 arc 總表第 80 項,產品決策題(後已修,M19,1.21.0 出貨) |
| 2 | 資訊系統只有「修改」權限的人,送一個「停用」欄位就等於做到「刪除」 | 低 | 總表第 81 項(A2 新登記) |
| 3 | 清單「每頁筆數」沒有上限 | 低 | 重複總表第 31 項(共用底層,全站清單都吃到;不另計) |
這支套件管兩張清冊:設備(客戶有哪些機器、伺服器)與資訊系統(客戶有哪些系統,例如人事系統、財務系統)。這兩張清冊是稽核工作的對象——稽核任務執行時會指向某台設備、某個系統,合規文件裡也會引用它們。
最大的一條(第 80 項)兩棒的工具都報了、首腦都核實了:
🔴 讀取類端點全部只檢查「有沒有登入」、沒有權限檢查,而寫入類每一個都有。 兩支路由檔都是這個形狀——設備的清單、選單、明細、被引用查詢,以及資訊系統的選單、清單、明細,全部只掛「要登入」;而新增、修改、刪除每一個都多一道權限檢查。
形狀與 FR-096 第 72 項、FR-097 第 75 項相同(讀取漏掉、寫入都有),但性質不同:那兩條是疏漏,這一條是套件契約檔裡寫明的刻意取捨,所以列為產品決策題而不是漏洞——細節見下方 A1 驗收。
資料庫隔離做得比先前幾支好(首腦 2026-09-16 對開發環境唯讀實查):
| 表 | 隔離 | 規則數 | 客戶欄位 | 資料量 |
|---|---|---|---|---|
| 設備 | ✅ 開 | 4 | ✅ 有 | 3 筆 |
| 資訊系統 | ✅ 開,且是強制模式 | 4 | ✅ 有 | 91 筆 |
所以本系列的重點不在「隔離有沒有開」,而在「程式這一層的權限檢查夠不夠」——與 FR-086/FR-095 那種「資料庫層全空」的情況不同,切棒與重點都照這個判斷排,掃完結果也印證了:兩棒沒有任何一條是資料庫隔離的問題。
八個權限點全部是客戶層級(設備四個、資訊系統四個)。這是正確的——資產清冊本來就該由客戶自己管,不是權限層級標錯。
| 棒 | 卡 | 範圍 | 檔數 | 狀態 | 首腦驗收 |
|---|---|---|---|---|---|
| A1 | CM-1814 | 設備全鏈+套件共用骨架與三支 SQL(jedi 套件) | 45 檔 | ✅ 掃完,1 條中等(另 1 條候選三票一致駁回) 報告|驗證章 verified |
✅ 已驗(2026-09-16) 屬實維持中等,但首腦改判性質為產品決策題;runner 兩個判斷皆覆核通過 |
| A2 | CM-1815 | 資訊系統全鏈+共用骨架重疊帶入(jedi 套件) | 42 檔 | ✅ **掃完,3 條(1 中等 2 低) 報告|驗證章 verified |
✅ 已驗(2026-09-16) F1 併第 80 項(同一產品決策)、F3 重複第 31 項(共用底層)、F2 新登記第 81 項**(低) |
兩棒各自獨立驗收完成。
⚠️ 兩棒相加是 87,但共用骨架 27 檔兩棒都算,去重後套件實際是 60 個檔案。 兩份檔數都在開卡當下實跑 git ls-files 驗過。
⚠️ 主專案宿主接線 12 支兩棒都不含,會與 jedi-log 的根層 6 支合併成獨立一棒(共 18 檔,BE repo)。跨 repo 必須分棒,工具一次只吃一個掃描根目錄。那一棒是下一個獨立 FR 的範圍,不在本站。
結論:那條發現屬實,維持中等,但首腦改判它的「性質」——它是產品決策題,不是漏掉。
| 項目 | 結果 | 白話 |
|---|---|---|
| 驗證章狀態 | verified,無拒收原因 |
完整跑完 |
| 候選 → 去重後 | 2 → 2 | — |
| 投票數 | 6(2 條 × 3 位檢查員) | 1 條 3:0 通過、1 條 3:0 駁回 |
| 未審候選 / 中斷 / 被降級 | 0 / 0 / 0 | 乾淨 |
| 耗時 | 3,670 秒(1 小時 1 分) | — |
| 掃描的程式版本 | cdb0d0f4,工作區乾淨 |
— |
| 範圍 | 45 檔,與工單逐檔對上 | ✅ |
事實完全正確:設備的四支讀取端點(清單 :37/選單 :56/明細 :68/被引用查詢 :106)只掛「要登入」,而寫入三支(:78/:90/:124)每一支都有權限檢查。
首腦核對了報告引的那句自陳:jedi_asset/plugin/contract.py:27 確實寫著「read 兩項 BE route 不守(守門只在寫入類)」——那句話真的在。
所以它與 FR-096 第 72 項、FR-097 第 75 項不是同一回事:那兩條是「寫入都有、讀取漏掉」的疏漏;這一條是程式碼裡寫明的刻意取捨。
要問的不是「為什麼漏了」,而是「當初這個決定,現在還算數嗎」。
但它仍需要產品面表態,因為現況是:「查看設備」這個權限只在前端隱藏選單、後端根本不擋。一個被刻意拿掉該權限的帳號直接打 API,一樣拿得到整份設備清冊——客戶管理員會誤以為拿掉權限就讀不到。
已登記跨 arc 總表第 80 項,中等。
一、主動駁回工具的另一條候選——正確。 工具說「沒開強制隔離,表擁有者可以繞過」,runner 指出實際連資料庫的角色不是表擁有者,對非擁有者來說一般隔離就已經生效,強制模式只在擁有者自己查詢時才有意義。首腦實查角色權限,結論一致。
二、指出工單本身有一處誤導——也正確。 首腦開卡時寫「設備表沒開強制模式是刻意取捨,代價要查」。runner 查完後指出:那個取捨在這個產品的部署方式下幾乎不影響任何實際行為,真正該關注的是新增規則少了管理員逃生門——而那是維運陷阱(平台管理員能查改刪任意客戶的設備,卻新增不了),不是安全漏洞。
這是首腦開卡時判斷偏了,runner 的更正是對的。
工具只實質碰到 ①(讀取端點沒守=F1)與 ③ 的一個角度(那條被駁回的誤判)。②④⑤⑥ 全是人工補上的。兩項值得留著:
| 項目 | 狀況 |
|---|---|
| 報告 | ✅ runner 自行交付(scan-A1-device.md) |
| commit | ✅ runner 自行 commit(0ea83527) |
| Notion 子卡回寫 + 狀態改「修正待驗證」 | ✅ runner 自行完成 |
| 修正卡 | ✅ 已處理——第 80 項後由 FR-114 修正線處理(M19-1~3 全數已修,1.21.0 出貨) |
✅ 交付四件齊全——本計畫第十一次做滿。
結論:三條發現全部屬實,但淨新增只有一條(第 81 項,低)。另外兩條一條併進第 80 項、一條是總表第 31 項的重複。沒有高風險。
A2 與 A1 掃的是同一個程式版本(cdb0d0f4),兩棒之間套件零 commit,所以兩份結果可以直接對照。
| 項目 | 結果 | 白話 |
|---|---|---|
| 驗證章狀態 | verified,無拒收原因 |
完整跑完 |
| 候選 → 去重後 | 3 → 3 | — |
| 投票數 | 9(3 條 × 3 位檢查員) | F1、F2 各 3:0 通過;F3 2:1 通過(異議在影響程度,不在路徑) |
| 未審候選 / 中斷 / 被降級 | 0 / 0 / 0 | 乾淨 |
| 耗時 | 3,374 秒(56 分) | — |
| 掃描的程式版本 | cdb0d0f4,工作區乾淨 |
與 A1 同版 |
| 範圍 | 42 檔,與工單逐檔對上 | ✅ |
事實正確:資訊系統的選單(information_system_route.py:45)、清單(:69)、明細(:105)只掛「要登入」;新增(:82)、修改(:114)、刪除(:135)每一支都多一道權限檢查。拿得到的是系統名稱、描述、機密性/完整性/可用性等級、狀態、部署模式、授權邊界、系統負責人。跨客戶仍被資料庫隔離擋住,只是同一客戶內外洩。
首腦判定:與 A1 第 80 項是同一個產品決策。 套件契約檔 plugin/contract.py:27 那句「讀取類端點不守、守門只在寫入類」一句話涵蓋設備與資訊系統兩邊,不是兩個獨立的漏洞。處置:第 80 項的描述擴為「設備與資訊系統兩張清冊」,補上資訊系統三支行號。
事實正確:修改端點(:124)的請求格式 InformationSystemUpdateSchema(api/serializers/information_system.py:59)允許送 is_active(是否啟用)欄位,資料存取層(information_system_repo_impl.py:127)照單寫入;而刪除端點(:136)做的事也只是把 is_active 設成 false。所以有修改權限、沒刪除權限的人,送一個 is_active: false 就等於刪掉了。
首腦判定:屬實,是新發現,維持低。 前端修改頁根本沒送這個欄位(前端只在清單篩選用到 is_active: true),所以這是純後端旁路;可逆(資料列還在),且只在自己客戶內。設備那半的修改格式沒有 is_active 欄位,不同病。
修法(二擇一):從 InformationSystemUpdateSchema 拿掉 is_active;或修改端點收到 is_active=false 時改要求刪除權限。
事實正確:資料存取層 information_system_repo_impl.py:60 直接 .limit(page_size),而 page_size 的來源是共用底層 jedi-common/jedi_common/interfaces/schema/common.py:13 的 PagerSchema.page_size,沒有範圍檢查(同檔的 page 有)。負值會一路到資料庫變 500。
首腦判定:根因在共用底層,不是資訊系統專屬——全站所有繼承 RequestMetaSchema 的清單端點都吃到;設備那半走另一條路徑(device_repo_impl.py:93/114)同樣沒上限。這正是總表 §3.1 第 31 項(FR-085 C3-2,同一行程式碼,中等,已登記)。A2 報告標「重複第 31 項,不另計」,並補一句:資訊系統與設備兩條分頁路徑都吃到,佐證第 31 項影響全站。修法一處修全站:PagerSchema.page_size 加 validate.Range(min=1, max=<上限>)。
工具只實質碰到 ①(讀取端點沒守=F1)。②③④⑤ 全是人工補上的:
app/oscal/service/ssp_resources_context_service.py:148-156 呼叫套件的正規查詢服務,走同一個資料存取層、同一套隔離規則,沒有繞過。plugin/assembly.py:74-90)缺任一必填插槽就拒絕掛載,資訊系統這半與設備共用同一個殼,A1 的正面結論適用。A1 已查過的四件(讀取不驗權限=同一決策/沒開強制隔離不是漏洞/空條件歸第 70/隔離與權限點層級正確),工具只重報了第一件(F1),已按規則併入第 80 項。
| 項目 | 狀況 |
|---|---|
| 報告 | ❌ runner 未交,首腦補寫(scan-A2-information-system.md) |
| commit | ❌ runner 未 commit,首腦補 |
| Notion 子卡回寫 + 狀態改「修正待驗證」 | ✅ 首腦補回寫 |
| 修正卡 | ✅ 已處理——第 81 項隨 M19 一併修完(1.21.0 出貨) |
🔴 runner 四件全未交——本計畫第八次,全部由首腦補寫。掃描本身是完整跑完的(驗證章 verified),沒交的是「掃完之後」那四件。
| 計數 | 變化 |
|---|---|
| 總表 §3.1 | 80 → 81(新增第 81 項) |
| 總表 §3 | 97 → 98 |
| risk-overview 低 | 37 → 38(資安類 20 → 21) |
| 全部 | 112 → 113 |
第 80 項描述擴為「設備與資訊系統兩張清冊」;第 31 項補一句「資訊系統與設備兩條分頁路徑都吃到」。
兩棒的分界是「設備/資訊系統」,共用骨架刻意重疊:
為什麼共用骨架要重疊:套件的守門殼、插件契約、錯誤碼、資料存取底層是兩半共用的,切在接縫上會讓兩棒都看不到全貌。重複報由首腦驗收時挑掉——接縫沒人看才是真的損失。
為什麼設備排第一:設備那張表刻意只開一般隔離、沒開「強制」模式,資訊系統那張開了。腳本檔頭說明設備不開強制的理由是「新增規則沒有留管理員逃生門且要求部門相符,開了會擋掉沒有部門歸屬的使用者」——這是刻意取捨,但取捨的代價要查。
這件事開卡時已讀過腳本檔頭,是本系列最值得追的技術點:
稽核流程的任務執行(三支查詢直接 import 設備的資料模型)、問卷、合規文件的資源庫。跨模組引用時,原本的隔離與權限檢查會不會被繞過,是本系列要看的接縫。
| 項目 | 值 |
|---|---|
| 主 session 模型 | Opus 5 (1M context),不要用 Sonnet |
| effort | low(單一研究員掃全範圍+三位檢查員投票) |
| focus | attack-surface(跳過測試碼、打包產物、文件) |
| 派工節奏 | 一次只派一棒,驗收完才派下一棒 |
掃完要逐項回頭核工單的「重點看什麼」。 快篩模式下工具常常只咬住一個最顯眼的攻擊模式,工單列的重點大半沒被碰到:
工具沒答的自己開檔查了再寫,標明「(工具未報,人工查證)」,並在報告可信度段誠實寫出哪幾點工具沒碰。報告格式抄 FR-097 L2,那一份的「卡片重點逐項人工查證」段是範本。
.claude/skills/security-scan-lead/SKILL.mddocs/features/security-scan-consolidated/~/Projects/Jedicogy/module/jedi-python-package/jedi-asset/main、BE repo main(2026-09-16 開卡時實查)以下全部由 build 掃資料夾產生,新增檔案重 build 即自動出現。標題連結指向渲染後的 HTML,md 連向源檔。
| 文件 | 類型 | 標題 | 最後更新 |
|---|---|---|---|
| scan-A1-device / md | 盤點證據 | A1 檢查結果:設備全鏈+套件共用骨架(jedi-asset) | 2026-09-16 |
| scan-A2-information-system / md | 盤點證據 | A2 檢查結果:資訊系統全鏈(jedi-asset) | 2026-09-16 |