145 條問題(資安 117 條+非資安的真程式錯誤 28 條)分成 44 組,建議開 24 張修正卡。
之所以組數比卡數多,是因為有幾組本來就該合在同一張卡裡修——例如檔案取得鏈那六條,只修其中一條等於沒修。
| 數量 | |
|---|---|
| 分了幾組 | 44 組 |
| 建議開幾張卡 | 24 張 |
| 未歸組 | 0 條 |
| 已修、不必再排 | 11 條 |
| 改了一半、這一條針對的事還在 | 10 條 |
| 原封不動 | 124 條 |
RUN_ENV=prod 那一半已經修好了(第 25 項),剩下的部分變得更划算。分組的判準只有一個:這幾條能不能用同一套修法一次解掉。 不是按套件分、也不是按嚴重度分——按套件分會把同一種病拆散到十幾張卡,按嚴重度分會讓同一條攻擊路徑的頭尾被排進不同輪。
起點是總表 §4 已有的十一組索引(🅰~🅺),沒有從零發明分法。本棒做的是三件事:
本棒沒有做的事:沒有開檔重驗任何一條(複查沒覆蓋到的一律照總表寫「仍在」)、沒有改總表一個字、沒有開 Notion 卡。
排序的依據是三件事:門檻有多低(要先有什麼才打得到)、不修會不會讓別的修法失效、修法有多確定(已裁定的、一行就能改的排前面)。
| 輪 | 這一輪做什麼 | 組 | 卡數 | 為什麼排這裡 |
|---|---|---|---|---|
| 第一輪 | 堵住「拿到帳密就繞過整個系統」與最低門檻的取檔路徑 | C1、A1 | 2 | C1 不修,後面所有應用層修法都白做;A1 門檻最低且決策者已裁「現在開卡」 |
| 第二輪 | 「只驗登入不驗歸屬」剩下八組一次做完 | A2~A9 | 8 | 修法形狀一樣,第二張之後照抄;同一批人連著做最省 |
| 第三輪 | 日誌這條線 + 憑證處置 | D1~D5、C2、C4 | 5 | 密碼外洩的完整鏈路,要一起收才算修完 |
| 第四輪 | 輸入不驗、資源耗盡、防竄改 | K1~K5、R1~R3、T1 | 4 | 彼此獨立,可以平行派 |
| 第五輪 | 資料庫隔離收尾 + 小修合卡 | B1~B3、X1、X2 | 4 | B 組大半已被 FR-094 修掉,剩收尾;X 組是順手做掉的小東西 |
| 待裁 | 要先定產品方向才能動程式 | P1~P7、I1、I2 | (1 張決策卡) | 修法不只一種選項,程式不能先動 |
跨輪的一條線:C 組(憑證)裡有幾條是「去後台按撤銷/換密碼」的動作,不是寫程式。那幾條不占開發時間,可以跟第一輪平行做。
每一組的格式固定:共同病根一句 → 涵蓋哪幾條 → 修法 → 怎麼驗 → 風險級別。 「涵蓋哪幾條」欄裡,編號後的括號標的是狀態;沒標的就是「仍在」。
整個 A 系列的共同病根:系統認得出「你是誰」,但從來不問「這筆資料是不是你的」。登入就放行。
九組共用同一套修法:在服務層補一道「這筆資料的主人是不是呼叫者(或呼叫者是不是這個專案的成員/管理者)」的檢查——每一組要抄的那支函式,都已經寫在同一個檔案的寫入方法裡。這不是設計新機制,是把已經存在的檢查補到漏掉的地方。
🔴 這一系列有一個驗收陷阱,每一組都適用:總表複查兩次都撞到「端點換上了看起來像守門的裝飾器,但那道守門從來不是歸屬檢查」(第 34、45、74 項)。驗收時不能只問「有沒有補守門」,要打開那道守門的實作看它到底檢查什麼。
病根:檔案的下載、換發免登入連結、刪除、服務層取檔,四個出口全都只驗登入。
| 條 | 是什麼 | 狀態 |
|---|---|---|
| 34 | 下載端點只驗登入 | 部分修(資料庫層已補、應用層沒動) |
| 35 | 換發不用登入就能下載的通行證,不驗歸屬 | 仍在 |
| 37 | 刪除任何檔案不驗歸屬 | 仍在 |
| 40 | 主專案側檔案服務層三個方法都只憑編號取檔 | 部分修(同 34) |
| 45 | 任務詳細 API 收了專案編號卻沒拿來用 | 部分修 |
| 47 | 存放檔案的資料表沒有隔離(最後一道防線) | 部分修(資料庫層已補) |
涵蓋範圍:2 支套件(jedi-file-upload、主專案側)+ 5 個檔案。
修法(四步,第三步要決策者放行):
managed_file_upload_service.py 的取檔/轉檔/刪檔三個方法)——這一層是唯一「已經把檔案撈出來、知道它屬於誰」的地方,真正該補的是這裡。⚠️ 34/40/47 三條的原文必須改寫再開卡——原文說「資料表沒有客戶歸屬欄位、隔離是關的」已經過期(FR-107 為了別的目的補上了)。照抄會讓接手的人去做一件已經做完的事,然後以為整條修完了。
怎麼驗:用 A 客戶的帳號,拿 B 客戶的檔案編號打下載、換通行證、刪除三支,都要回 403(現在是成功)。同租戶內跨專案也要擋。DEV 唯讀可以先查資料庫現況,實際打端點要在 DEV 做。
風險級別:🔴 高(組內最高:34/35/40/47 四條高風險)
病根:稽核流程引擎裡,同一個檔案的寫入方法都有歸屬檢查,讀取方法全部漏掉。
| 條 | 是什麼 |
|---|---|
| 49 | 讀證明清單只驗登入(拿到檔案編號後可接 A1 直接下載檔案本體) |
| 50 | 讀單筆證明沒有歸屬檢查(目前被另一個程式錯誤擋住,那個錯誤一修就真外洩) |
| 51 | 流程留言讀寫都只驗登入(可冒充同事名義發言釣魚) |
| 52 | 讀稽核階段歷程完全沒有權限檢查 |
| 53 | 讀階段資訊:用專案編號查角色、用另一個輪次編號撈資料,兩者不核對 |
涵蓋範圍:jedi-flow-engine + 主專案側 · 4 個檔案。
修法:
assert_project_participant。advance_stage/rollback_stage 兩支的輪次歸屬比對——目前跨專案寫入是靠下游套件的第二道檢查在擋,這一層自己沒檢查。不補的話,將來新增一支不走那個套件的處理函式,洞就重新打開。怎麼驗:A 客戶帳號拿 B 客戶的任務編號/輪次編號打這五支,全部要 403。第 50 項要在修完序列化錯誤之後再驗一次。
風險級別:🔴 高(49/51 兩條高風險)
病根:成員名冊與任務指派的讀取全部沒有權限檢查,而且查詢條件全是選填——送一個空請求就回整張表(實測:成員名冊 751 筆、任務指派 12,494 筆,跨所有客戶)。
| 條 | 是什麼 |
|---|---|
| 60 | 專案層成員名冊讀取無檢查、空請求回全表(這是整組的資料源頭) |
| 61 | 控制項層成員名冊兩支同樣無檢查 |
| 62 | 第六支成員服務整個檔案零權限檢查(目前沒有 API 入口,接上就開) |
| 63 | 流程參與者的兜底檢查寫在提前返回之後,永遠執行不到 |
| 64 | 寫入時不驗 group_id/control_id 是不是真的屬於這個專案 |
| 68 | 任務指派清單只驗登入、八個條件全選填 |
| 69 | 新增指派用自填的專案編號判管理者,不驗任務歸屬 |
| 71 | 更新指派撈不到紀錄時整段跳過管理者檢查 |
| §3.2 17 | 三支服務的「用編號查資料」永遠回空——補完權限拿這條路測會得到假通過 |
| §3.2 19 | 流程參與者表 DEV 0 筆、改刪必出錯(就是第 63 項造成的) |
| §3.2 20 | 專案啟動時的成員同步刻意繞過套件守門(設計自陳,記錄不判) |
涵蓋範圍:jedi-task-platform + 主專案側 · 約 10 個檔案。
修法:
delete_task_assignee 寫法補檢查,專案編號改必填。與 I2 的關係:60/61/68 的「空請求回全表」根因在共用底層(I2 第 70 項)。決策者 2026-09-15 已裁「要在底層擋,但分兩步,第一步先盤點」。這張卡走的是第二條路——逐支補「專案編號必填+成員檢查」,不等底層改;底層那件事照原裁定另案進行。
怎麼驗:送空白請求給那幾支,要回 400(欄位必填)而不是整張表;帶別人的專案編號要回 403。驗之前先確認 §3.2 第 17 項已修,否則結果不算數。
風險級別:🔴 高(60/69 兩條高風險)
病根:這是整個掃描計畫裡「補權限只補了一半」最乾淨的一次實證——填答功能 14 個入口,6 個寫入全部有檢查(6/6),8 個讀取一個都沒有(0/8),而且在同一個服務檔案裡。
| 條 | 是什麼 |
|---|---|
| 89 | 查填答歷史明細,空請求整包讀走全客戶所有問卷的每一版答案與審核意見 |
| 90 | 讀某份任務問卷的答案不檢查是不是你的 |
| 91 | 列出任務問卷不限範圍(同時是第 90 項的入場券) |
| 92 | 列出填答歷史不限範圍 |
| 94 | 還原歷史版本不檢查那個版本是不是這份問卷的 |
| 95 | 即時同步的房間想進哪間就進哪間 |
| 96 | 問卷討論列表送空查詢就撈回全公司討論 |
| 97 | 改/刪討論不驗是不是本人寫的,改完還掛原作者名字 |
涵蓋範圍:jedi-survey · 約 8 個檔案。
修法:套件裡已經有現成的 assert_task_survey_writer 與對應的讀取守門,逐支掛上即可;91/92/96 三支的查詢條件改必填。97 若產品面決定「管理員可以刪別人的留言」,要走一條寫明白的管理路徑,照樣檢查他是不是這個專案的人。
這一組要帶一句寫進卡片:2026-07 那次統一補權限的工作只涵蓋了寫入。往後任何一次補權限的驗收,都要把讀取入口分開數一遍。
怎麼驗:A 部門帳號拿 B 部門的問卷編號打這八支,全部 403;空請求要 400。即時同步那兩支要另外開連線測。
風險級別:🔴 高(89/90 兩條高風險)
| 條 | 是什麼 |
|---|---|
| 65 | 專案摘要報告清單與歷史版本四支讀取只驗登入(含稽核結論全文) |
| 66 | 稽核輪次選單一支只驗登入 |
修法:照抄同檔已有的 assert_project_participant,一行。跨客戶已被 FR-094 的資料庫隔離接住,現在只剩同客戶內跨專案。
風險級別:中。建議併入 A3 同一棒做(同一個人手上,抄的是同一支函式)。
| 條 | 是什麼 |
|---|---|
| 85 | 「測試連線」不驗權限——按一下就把掃描工具帳密解密送到按的人指定的主機(🔴 高) |
| 86 | 同一支端點,目標主機由呼叫者指定、不比對白名單——代理程式變成任意連線跳板 |
| 88 | 查掃描執行紀錄少了專案參與者檢查(同服務另外八支都有做) |
修法:85 掛上同檔其他三支在用的「工具設定修改」權限點;86 目標主機限制成存好的設定範圍;88 補一行參與者檢查。
⚠️ 85 與 86 必須同卡:補了權限(85)不會讓 86 消失,只是把門檻從「任何登入者」提高到「工具管理員」。只修 85 就結案,是把一個對外的跳板留給內部人。
風險級別:🔴 高。
| 條 | 是什麼 |
|---|---|
| 108 | 預覽任意 Google 雲端硬碟檔(🔴 高,本 arc 唯一高風險) |
| 109 | 查結果、查報表不驗專案成員 |
| 111 | job 列表/單一狀態不驗專案,且進度登記簿是全程序共用、不分客戶 |
這組要先裁一件事(總表 §7 第 19 項):舊線已標 legacy、前端入口已經拿掉,後端三支路由仍掛著。刪那三支路由一次消掉這三條;留著就要三條各補守門。
建議:先刪路由。理由是前端已經沒有入口,留著的三支路由是純風險、零價值;補守門要寫的程式比刪路由多,而且補完還是沒人用。
風險級別:🔴 高(108)。但如果裁定刪路由,這張卡會縮成一個 10 分鐘的工作。
| 條 | 是什麼 |
|---|---|
| 1 | 公告四個漏洞(AI 儀表板繞權限讀全租戶公告含草稿/改刪不驗歸屬/單筆讀取零檢查/無部門帳號全放行) |
| 8 | AI 儀表板讓任何登入帳號列出全公司帳號、角色、租戶、部門清單 |
修法:公告那四個有現成的檔名行號可以直接抄。第 8 項的正規做法是讓 AI 儀表板申報的每支查詢各自標明需要什麼權限,最快的止血是把那四支查詢從 AI 可用清單移除。
⚠️ 這組跟 P6(第 10 項「視同管理員」後門)同在 AI 儀表板上,但那條是刻意設計、要先裁產品方向,不要一起修。
風險級別:中。
| 條 | 是什麼 |
|---|---|
| 58 | 流程範本列表與單筆讀取沒掛「讀取流程範本」能力點(能力點存在、選單也綁了,就是 API 沒掛) |
| 113 | detection-profile.read 資料庫早宣告、前端矩陣也認,後端七支讀取一支都沒檢查 |
病根跟 A1~A8 不同:那些是「忘了寫檢查」,這兩條是「權限點宣告好了,後端沒接上去」——結果是租戶管理員以為拿掉權限就讀不到,實際上 API 完全敞開。
修法:各補一行掛上既有能力點。
要帶進卡片的一句:這種病跟 P3(第 80 項資產清冊)長得很像,但性質相反——P3 是程式碼契約自己寫明「讀取不守」的刻意取捨,這兩條是漏接。不要一起處理。
風險級別:中。
| 條 | 是什麼 | 狀態 |
|---|---|---|
| 43 | 13 張表隔離沒生效(實測曾看到 39 筆待辦、213 筆專案) | 部分修(甲乙丙戊四組已由 FR-094 全部開完) |
| 44 | 4 個畫面直接繞過隔離 | 已修 |
| 5 | 三張表訂了規則但開關沒開 | 已修 |
| 4 | 公告與部門關聯表沒訂規則 | 仍在 |
現況:這組實質上只剩兩條。第 43 項只剩一張 config.log_forwarding_settings 沒處理,而那張正是報告自己標「建議重新分類、不算隔離缺口」的、且牽涉 P2(第 75 項)。
修法:第 4 項走 sql-migration 標準流程。⚠️ 開卡時務必寫明:bulletin_org_units 只有兩個欄位、沒有客戶歸屬欄位,不能照抄母表 bulletins 的四條規則——要嘛透過母表借隔離,要嘛先加欄位。不寫這句,接手的人幾乎一定會照抄然後失敗。
風險級別:低(剩下的部分)。建議降到第五輪收尾做。
| 條 | 哪些表 |
|---|---|
| 23 | system_logs(668,813 筆)與 api_logs 兩張日誌表 |
| 7 | jedi-issue 五張表(問題單、成員、三張關聯表) |
| 47 | 檔案表(✅ 資料庫層已修) |
| 67 | oscal.profile_imports/ssp_implemented_requirements |
| §3.2 22 | 任務指派的驗證觸發器沒真的建起來,而且它讀的三個欄位在表上不存在 |
| §3.2 31 | 基準的領域層與存取層四個檔零隔離程式碼(前提記錄,不是要改的錯) |
| §3.2 32 | detection_profile_controls 零隔離全靠約定(脆弱設計記錄) |
⚠️ 這組不能跟 B1 排同一輪。B1 是「開關打開」,這組是「先改資料表結構、回填既有資料、再補規則」——而且 system_logs 那張有 66 萬筆要回填。
修法:每張表都是「加欄位 → 回填 → 開隔離 → 補規則 → 出貨基線同步」五步。建議一張表一張卡,不要併成一張大卡。
要先裁的(總表 §7 第 8 項):兩張日誌表到底要不要做客戶隔離,還是明確定位成「只給內部維運看的全域資料」、改成限縮誰能查就好?後者不用改表結構,成本差一個數量級。這件事沒裁,B2 這組動不了。
§3.2 第 31、32 項不開卡——總表自己標明是「前提記錄」與「脆弱設計記錄」,不是程式錯誤。建議寫進資料庫設計文件,讓下一個改動的人知道這裡的安全是靠什麼撐著。
風險級別:🔴 高,但被「要先裁方向」擋住。
第 87 項:把組織路徑 /1/102/ 切成 [1, 102] 當白名單,結果子單位看得到母單位的資料(還能改能刪),母單位反而看不到自己底下子單位的。該擋的沒擋、不該擋的擋了。
這條最不容易被發現,因為從外面看「隔離有開」。DEV 實查確認母子結構真的存在、資料全在子單位,兩面都已經在發作。
涵蓋範圍:9 張表跨三個套件(jedi-detection 5 張+遠端代理程式 agent_tasks +三張授權表)+出貨基線。
修法:改判斷式即可,但要一次改 9 條、且動到出貨基線(屬決策者裁示)。
風險級別:中,但這是資安與功能雙錯——母單位看不到子單位的資料是個功能 bug,客戶會直接回報。
| 條 | 是什麼 |
|---|---|
| 39 | 任何登入帳號打一支查詢就拿到自己客戶的雲端儲存位址、帳號、密碼明文(三層防護一起破) |
| 72 | 讀取系統設定的三個入口只驗登入(同檔寫入四個入口每個都有檢查) |
| 73 | 密碼遮罩名單漏掉物件儲存那一組 |
🔴 這三條必須同一張卡。只補權限(72)不補遮罩(73),有正當權限的管理員打開頁面時瀏覽器仍會收到共用密鑰明文——任何看得到他瀏覽器流量、存檔或前端錯誤日誌的人都拿得到。只修一邊等於沒修乾淨。
修法:
為什麼排最前面:不修這條,應用層補再多檢查都沒用——拿到那組帳密可以完全繞過整個系統直連儲存空間。
怎麼驗:用一個零權限的登入帳號打那三支查詢,回應裡不能出現任何密碼欄位;用有權限的帳號打,密碼欄位也要是遮罩後的值。
風險級別:🔴 高。
| 條 | 是什麼 | 性質 |
|---|---|---|
| 2 | 資料庫密碼、四家 AI 服務金鑰、Nexus 與 MinIO 憑證寫進版控 | 換憑證 |
| 3 | 安裝程式每套部署種同一組原廠超管密碼 | 出貨預設值(見 P7) |
| 83 | jedi-issue 歷史裡第二把 GitLab 權杖,從沒被撤銷過 | 🔴 去後台按撤銷 |
| 84 | cmmgr 密碼+兩組產品帳密寫在需求文件裡,那份文件已經發佈到公開網站 |
🔴 換密碼+清檔 |
🔴 第 83、84 兩項不是「要不要修」的問題,是一個動作。83 是去 gitlab.com 後台按撤銷(並查該帳號從 2025-04 起的稽核紀錄);84 是換密碼並把公開站上那頁清掉。這兩件不占開發時間,可以跟第一輪平行做。
⚠️ 決策者 2026-09-19 已裁「三個例外也不先做」(含第 84 項)——理由是快掃完了、不分批。掃描現在已經收口,這條裁定的前提消失了,建議請決策者重新確認 83/84 要不要立刻處理。
已裁定不必再問的:測試機專用的資料庫與管理帳號密碼不需更換;不重寫 git 歷史。
風險級別:🔴 高(84:不用登入就取得、且是繞隔離的帳號)。
| 條 | 修什麼 |
|---|---|
| 19 | 主產品連 Redis 寫死不驗憑證——另一個套件已經修好的同一個漏洞的複製品,照抄現成修法+現成測試 |
| 29 | 忘記密碼的信箱遮罩,套件預設改成開啟(主專案已覆寫,但套件預設不安全) |
| 42 | 連物件儲存預設改成開加密 |
| 117 | 建掃描基準時放行明文 http://,且網址型來源不記指紋 |
四條都是一行改預設值。建議併進 X1 一起做,不單獨開卡。
風險級別:中(19 最高,因為是已知修法的漏網複製品)。
| 條 | 是什麼 |
|---|---|
| 107 | 派工時把解密後的客戶機房登入帳密另存一份明文進工單表——那份從頭到尾沒有任何程式讀過,而且沒有清理機制、累積無上限 |
| 103 | AI 金鑰走 docker run 命令列,同機任何帳號 ps 看得到(落地版跑不到) |
修法:107 刪掉寫入那一行 + 補一支清存量的 migration。103 改 --env-file 或 -e KEY 不帶值。
107 值得單獨強調:產品刻意做的加密保護被這一行繞過了——拿到資料庫備份、pg_dump 檔或唯讀帳號的人,一句 SQL 就得到客戶正式機房的可用 SSH 密碼。而且那份資料沒有任何人在用。刪掉它沒有任何副作用。
風險級別:中,但 107 的投入產出比極高(刪一行 + 一支 migration)。
第 6 項:開發環境的私鑰簽出來的授權檔,正式環境的驗證也會通過。三個環境的公鑰全部編譯進同一份後端程式。
決策者已裁:現階段不處理,等正式簽發站建好之後一併處理。程式檔頭註解說明這是刻意設計(為了支援日後換發新公鑰不中斷)。
這一條列在這裡只為了「每條都有交代」,不建議現在開卡。
| 條 | 是什麼 | 狀態 |
|---|---|---|
| 22 | 登入密碼與憑證原文直接寫進日誌檔與資料庫 | ✅ 已修(09-20 複查:四個 log 檔實際 grep,明文 0 筆) |
| 30 | 全站唯一那道遮罩機制,遇到含引號的密碼只遮一半 | 仍在 |
| 18 | 竄改回報把伺服器日誌最後 50 行原文送到原廠 | 仍在 |
第 22 項雖然已修,但留下兩件殘留,建議寫進這張卡:
第 30 項的修法(總表 §7 第 7 項已寫明方向):改成先把內容解析成結構化格式再逐層遮蔽。這會動到全站唯一的這道遮罩機制,屬核心共用邏輯——依測試政策,這一條要補寫測試。
風險級別:中(22 已修後)。
| 條 | 是什麼 | 狀態 |
|---|---|---|
| 23 | system_logs 沒隔離、也沒有可用來隔離的欄位(668,813 筆) |
仍在(同 B2) |
| 24 | 完整錯誤堆疊寫進那張沒隔離的表 | 部分修(風險反而被放大) |
| 25 | 出貨設定沒標「這是正式環境」 | ✅ 已修 |
| 26 | 監控功能載入就執行 | ✅ 已修 |
| 27 | 兩種日誌類別在正式環境寫死最詳細等級 | 部分修(改掉一項,剩兩棵仍寫死 DEBUG) |
| 79 | 兩張日誌表的保存期限從未生效 | ✅ 已修(已接上每日 03:30 排程) |
| §3.2 11 | 寫資料庫日誌失敗會連帶弄壞使用者的請求 | 部分修(風險反而被放大) |
🔴 這組有一個要特別講清楚的:第 24 項與 §3.2 第 11 項在這段期間風險反而變大了。同一支改動(CM-1920)把資料庫日誌處理器補掛到正式與測試環境——它修的是「寫多少」,而「寫失敗會弄壞使用者請求」「錯誤堆疊落在沒隔離的表」這兩件事沒碰,等於原本只在開發機的問題,現在正式環境也會走到。
修法:
emit() 全函式還是沒有錯誤處理,補上 try/except,一個小改。sqlalchemy.orm 與 pymongo.event_loggers 兩棵調回 WARNING。好消息:這組七條裡三條已修,剩下的四條都是小改(一個 try/except、一個不存堆疊、兩個調等級)。投入產出比很高。
風險級別:中。
這三條合起來是一條完整攻擊鏈:
| 條 | 是什麼 |
|---|---|
| 75 | 客戶的管理員改得動「全公司日誌要送去哪」(🔴 高) |
| 76 | 路上完全沒加密、不必解密就看得到 |
| 77 | 還能在裡面塞偽造紀錄混淆追查 |
與 D1 第 22 項直接相扣——日誌裡有密碼原文,所以這條管道外洩的就是密碼本身。
第 75 項要先裁產品方向(見 P2),76/77 不用等:76 補加密選項、77 過濾換行符號(gelf 那半已經有現成作法可抄),兩條都可以現在做。
建議:這張卡拆成兩段——76/77 現在做,75 等 P2 裁完再接上。
風險級別:🔴 高(75)。
| 條 | 是什麼 |
|---|---|
| 78 | 匯出操作記錄的 Excel 沒過濾公式字元——種下去不需要任何權限,在任何權限檢查跑之前就記下來了(🔴 高) |
| 82 | 匯出意見回饋的 Excel/CSV 同一種病 |
修法:兩處共用一支「開頭是公式字元就前置單引號」的中和函式。同一種病兩個位置,一次修完。
風險級別:🔴 高(78:不用登入就能種,唯一門檻是等管理員自己打開檔案)。但修法只有一支小函式——建議提前到第一輪順手做掉,不要排到第三輪。
| 條 | 是什麼 |
|---|---|
| 100 | 問卷資料夾列表把資料庫原始錯誤訊息整句吐回前端(含表名、欄位名、SQL 片段) |
| §3.2 25 | 證據分類失敗時把上游例外原文存進批次、前端可讀 |
修法:100 把那段「所有例外都接住」的程式拿掉,讓框架的錯誤處理器回標準錯誤碼;§3.2 25 改存固定錯誤碼+一句白話,原文只進 log。
風險級別:低。
| 條 | 是什麼 |
|---|---|
| 9 | AI 儀表板查詢結果夾帶密碼加密用的鹽值 |
| 12 | AI 儀表板回應夾帶鹽值與「是不是超級管理員」旗標 |
| 33 | 套件共用的序列化工具原樣吐出整個物件、零欄位過濾(上面兩條只是它造成的個案) |
🔴 修第 33 條才是治本,只修 9/12 這兩個個案,之後還會有新的個案冒出來。
修法:在套件層的序列化工具加白名單或黑名單參數(至少擋掉密碼、鹽值、憑證這類欄位名);9/12 同時加欄位白名單或重用既有查詢已經寫好的排除設定。
⚠️ 33 在 jedi-common,改了要發版才生效,節奏跟只改主專案不同。
風險級別:中。
apply=False 大量指派(2 條 · 建議開 1 張卡)| 條 | 是什麼 |
|---|---|
| 98 | 資料夾更新塞一個「已刪除」欄位就繞過「非空資料夾不可刪」守門,造出孤兒資料 |
| 99 | 資料夾列表蓋掉內部的「排除系統資料夾」開關,叫得出快照與已刪除的資料夾 |
病根:網址入口那行負責「檢查前端送來的欄位對不對」的宣告被加了 apply=False——叫框架完全跳過驗證,那一行只剩裝飾作用。業界叫「大量指派」。
修法:拿掉 apply=False,明確宣告允許的欄位。⚠️ 同樣寫法在問卷套件的四個網址入口上都有,四個一起改,不要只修被掃到的那兩支。
🔴 這張卡要附帶一件盤點工作(總表 §5 已列):另外 20 支套件要搜一遍有沒有同樣寫法。這件事比修這兩條更有價值——apply=False 是一個可以用一行 grep 找遍全公司的形狀。
風險級別:中。
| 條 | 是什麼 |
|---|---|
| 36 | 上傳的網頁檔在我們自己的網域裡被當程式執行(儲存型 XSS),副檔名完全不限制(🔴 高) |
| 101 | 代理程式自報的檔名原樣存成證據檔,稽核人員預覽時 .html 會在瀏覽器裡執行 |
同一種病的兩個入口:一個是使用者上傳、一個是代理程式回報,但落地點是同一支預覽端點(依副檔名決定型別、而且是直接在瀏覽器裡開不是下載)。
修法:預覽端點改成不依使用者自填的副檔名決定型別、危險型別一律強制下載;上傳與回報兩側都補副檔名白名單、去掉路徑。
風險級別:🔴 高(36)。
| 條 | 是什麼 |
|---|---|
| 115 | 上傳的掃描規則包原封交給外部工具,那工具會把裡面的設定檔當 Ruby 樣板先執行再解析(🔴 高) |
| 112 | 「最多一萬個檔」的上限對 .zip 形同虛設(打開那一刻就整份展開進記憶體) |
| 116 | 網址型規則來源完全繞過壓縮檔驗證器(三道上限只接在上傳分支) |
112 與 116 是同一支驗證器的兩種病:112 是「上限存在但太晚生效」,116 是「上限根本沒接進這條路」。一起修。
修法:115 改成解析前先剝掉或轉義樣板語法(或換一個不執行樣板的解析方式);112 改成逐筆讀;116 把驗證器接到網址分支的呼叫點。
風險級別:🔴 高(115)。
| 條 | 是什麼 |
|---|---|
| 21 | 資料庫隔離用的連線變數用字串拼接組進 SQL(三位檢查員一致認為目前不可被利用) |
| 110 | 查 Google 雲端硬碟的搜尋條件字串拼接、沒跳脫(未實測) |
這組記的是「寫法本身不安全」,不是「現在就有漏洞」。擋住第 21 項的是外部環境的巧合(值的來源剛好是整數主鍵與資料庫查出來的字串),不是寫法本身安全。
建議:趁現在改掉,不要指望以後有人會一直記得這個限制。 改成參數綁定,成本很小。
風險級別:低(但形狀不好)。
第 105 項:在一張稽核任務上換掃描工具時,「要掃哪些機器」不會拿實際生效的值重新檢查台數上限——先綁一支不設上限的工具、填一個超大網段,再換工具,舊的超大網段跟著留到新工具底下,執行時逐台展開吃爆記憶體。
修法:換工具時用實際生效的值重跑一次上限檢查。
建議併入 A6(同一支套件、同一批人)。
這組跟其他組的修法完全不互相影響,可以任何時候獨立排。
| 條 | 是什麼 |
|---|---|
| 13 | 換掉驗證簽章的函式庫,整套機制永久失效——已實測證實(🔴 高) |
| 14 | 文件宣稱兩道鎖,程式只做了一道,刪一個檔就能讓鎖定的機器重開(🔴 高) |
| 15 | 環境變數可以換掉「要核對哪個目錄」(這是 13 的放大器,單獨修意義不大) |
| 16 | 解鎖紀錄毀損時預設當作「一張都沒用過」 |
| 17 | 鎖定畫面洩漏機器指紋與事件編號 |
| 18 | 回報功能夾帶日誌內容(同 D1) |
要先裁的兩件(總表 §7 第 9、10 項):
⚠️ 15 必須跟 13 同一張卡,單獨修沒有意義。
這組還有三個相鄰面向從頭到尾沒碰過(總表 §3.4):解鎖檔的簽發端(在 License Center)、驗章的加密邏輯本身、打包出貨時產生清單檔的流程——最後這件直接決定防竄改實際保護的範圍有多大。建議寫進卡片當已知缺口。
風險級別:🔴 高。
| 條 | 是什麼 |
|---|---|
| 55 | 惡意流程圖卡死處理執行緒(🔴 高,決策者 09-13 裁升級) |
| 56 | 一筆空字串範本讓所有人的清單頁出錯、不會自己恢復 |
| 57 | 「檢查流程圖」API 任何登入帳號打一次卡住 120 秒、連打四次全站不回應(🔴 高,同裁定) |
| §3.2 15 | 相關的一條路徑(已隨 v1 殘留端點清理順手消失) |
55/56/57 是同一個根本原因(不信任使用者送進來的 XML),總表已建議合成一張「BPMN 輸入強化檢查」的卡。
修法分三段:
module_frame_item_route.py,跨程式庫的修改要注意。風險級別:🔴 高。
| 條 | 是什麼 |
|---|---|
| 31 | 分頁「一頁幾筆」沒有上限(全站共用底層,兩支路徑都撞到過) |
| 38 | 上傳沒有單檔大小與檔案數量上限 |
| 104 | 分類容器無記憶體/CPU/處理程序上限,逾時殺不掉容器(落地版跑不到) |
| 114 | 手動重新掃描無條件開背景執行緒,連打幾百次就是幾百條執行緒 |
第 31 項最划算:改一個共用底層的預設上限,全站所有分頁一次受保護。而且它不會被既有的「請求大小上限」擋住——攻擊形狀是「請求很小、要求回傳的資料很大」。
第 114 項修法極便宜:服務裡早就有 running 狀態且有在寫入,只是沒人拿來判斷。
風險級別:中。
🔴 這一整個系列不是「要不要修」,是「要修成什麼樣」。建議合成一張決策卡請決策者一次裁完,而不是七張卡各問一次。
| 組 | 條 | 要決定什麼 | 狀態 |
|---|---|---|---|
| P1 | 59 | viewer 能不能完成/退回稽核任務 | ✅ 已裁(2026-09-13):不可以,除非他就是被指派的人。修法已定案,可以直接開卡。⚠️ 修法範圍要含弱點掃描模組的八支改狀態端點(吃同一道守門,viewer 可發動帶帳密的掃描與刪紀錄) |
| P2 | 74、75 | 客戶的管理員該不該有權改登入安全政策/日誌轉送目的地(現況:有權,而且改到的是全公司共用的那一份) | ✅ 已有第四個方向(2026-09-16):只給客戶自己的第一層租戶(總部)改,子公司/部門不給;root 租戶維持不開放。⚠️ 該案套到日誌轉送表同樣要先改表結構(那張表也只有全域一列、tenant_id 寫死 NULL) |
| P3 | 80 | 設備與資訊系統清冊「只要登入就能看、不分權限」這個刻意取捨還算不算數 | 待裁。⚠️ 與意見回饋那五顆權限點(總表 §7 第 16 項)是同一種題,建議一次裁 |
| P4 | 41 | 讀不到自己的儲存設定時去借別家客戶的帳密,是不是刻意的「共用儲存空間」設計 | 待裁 |
| P5 | 11、102 | AI 提示注入:使用者打字就能誘導 AI 選中 26 支查詢中的任何一支(11)/證據內文可以對 AI 下指令左右分類結果(102) | 待裁。102 要先定「AI 分類結果要不要當半可信」 |
| P6 | 10 | AI 儀表板專案清單的「視同管理員」後門——刻意設計、不是寫錯,但在「使用者打字、AI 自己決定查什麼」這個新情境下從沒重新檢視過 | 待裁 |
| P7 | 3 | 出貨時預設密碼的政策 | 決策者已裁「先記錄、之後再看」 |
P1 與 P2 已經裁完了,可以直接開卡——建議把這兩組從決策卡裡拿出來,併進第二輪跟 A 系列一起做。
| 條 | 牽動關係 | 狀態 |
|---|---|---|
| 46 | 兩支背景排程靠「沒有登入身分時給最高權限」撐著,收緊 CM-1559 會讓它們悄悄停止運作、不報錯 | ✅ 已修(改成具名系統身分) |
| 53 | 修第 53 條時要一併補 advance_stage/rollback_stage 兩處 |
仍在(已含在 A2) |
第 46 項已修,這組實質上只剩「修 A2 時記得第 53 項的連帶」這一句話。不用獨立開卡,寫進 A2 的卡片即可。
第 70 項:六張表的資料存取層沒有一支自己加專案範圍條件——全部走共用底層「查詢欄位有值才加條件、沒值就不加」的規則。這個底層行為已經連續三次在不同套件放大成全庫外洩(檔案清單、成員名冊、任務指派)。
決策者 2026-09-15 已裁:要在底層擋,但分兩步。 第一步先盤點全站哪些地方是刻意要查全表的(碼表、排程、管理員總覽),改成明確標記;第二步才動底層。兩步之間可以隔很久。
🔴 第一步的起點已經備妥——第十二任首腦做完的 17 支盤點清單(STATE「空條件回全表:全域盤點第一版」段),下一任可以直接拿來用,不必重掃。那份清單還附了判準:看這張表的一筆資料有沒有「主人」——有主人就該拒絕空條件,沒主人(碼表、公版、全站共用字典)回全表是正確的。
建議:這件事獨立開一張卡,不要跟 A3/A4 綁在一起——A 系列走的是「逐支補檢查」那條路,不等底層改。
這些問題彼此不相干,但都很小,一次順手做掉。
| 條 | 修什麼 |
|---|---|
| 54 + §3.2 13 | 階段推進/回退兩處 ctx.setdefault 改成直接覆寫(操作人一律以登入身分為準)+資料格式定義加白名單 |
| 81 | 資訊系統修改的資料格式把「停用」欄位拿掉(目前只有修改權限就能達成刪除效果) |
| 93 | 問卷即時同步寫答案時「這筆是誰填的」改用登入身分,不採用前端送的名字 |
| §3.2 12 | 密碼產生器少算一個字元(-4 改 -3)——目前產出的密碼可能通不過自家的密碼政策 |
| §3.2 21 | 「批次新增指派」死端點:後端只有 return []、前端仍在呼叫 |
| §3.2 24 | 問卷 Excel 匯入失敗時暫存檔永遠留在磁碟(刪檔那句移進 finally) |
| §3.2 26 | 正解匯入加筆數上限與型別檢查 |
| §3.2 27 | AI 分類設定的「預設廠商」「預設型號」存得進去但沒人讀 |
| §3.2 30 | 一段註解寫的跟資料庫實際規則相反 |
| §3.2 33 | 共用分頁查詢把跨欄位字串條件用「或」而不是「且」連接(篩選條件被放寬不是收緊) |
| C3 的 19/29/42/117 | 四條改預設值(見 C3) |
建議:這張卡不要一個人做完——15 個位置散在五、六支套件裡,按套件拆成兩三批平行做比較快。
| 條 | 刪什麼 |
|---|---|
| 20 | db.py:97-99 三行死碼——留著會讓人誤以為那裡有一道組織層級的權限檢查 |
| 32 | 開發用的輔助工具混在出貨套件裡(會把檔案覆寫成空白、載入就讀 AI 金鑰環境變數) |
| §3.2 14 | bpmn_generator.py 三支吃檔案路徑、零呼叫者的方法——是一個已經裝好、隨時可能被拿來任意讀寫檔案的陷阱 |
| §3.2 16、18b、23 | 三組「已接線但沒人用、且零權限檢查」的服務——接上去就等於憑空多出完全沒守門的入口 |
這組的價值不在「現在有洞」,在「留著會害下一個人判斷錯」。
修法:直接刪,或在組裝的地方加一句明確的提醒註解。§3.2 16/18b/23 那三組如果要留,要標明「啟用前必須先修第 63 項」。
§3.2 第 7、8、9、10 項,兩次複查都確認修好了。列在這裡只為了讓 145 條每條都有交代。
這些條目找不到能一起修的同伴,硬塞進哪一組都是勉強。 標在這裡是誠實的分類結果,不是漏掉。
| 出處 | 條 | 是什麼 | 建議 |
|---|---|---|---|
| §3.1 | 28 | 員工被停權後登入憑證還能用約三天半,而且自己還能續到約八天 | 獨立開卡。這條的修法橫跨停權動作、每個請求的身分確認、資料查詢層三處,跟誰都不同組 |
| §3.1 | 48 | 本機硬碟刪檔漏清轉檔產生的 PDF 備份(雲端那邊有清) | 併進 A1 順手做(同一支套件、同一個刪檔路徑) |
| §3.1 | 106 | 刪除整批之後,判定結果、容器報告、含原始檔名的清單全部永久留在主機工作目錄 | 獨立小卡 |
| §3.2 | 18 | 沒部門的使用者送意見回饋會失敗、畫面看不出原因 | 要先裁甲/乙/丙哪個修法(總表 §7 第 17 項) |
| §3.2 | 28 | SHARED 範圍值三層各認一套,服務層那層是空的 |
總表標明「只回報待裁、不直接開卡」 |
| §3.2 | 29 | 套件自帶建表腳本的值域還停在舊版 | 同上,且屬出貨基線待重產類——重不重產由決策者裁 |
本棒只寫草案,沒有動總表一個字。 下面是核對 145 條時發現的對不上的地方,由首腦裁定後另派一棒改。
| # | 在哪 | 現況 | 建議 |
|---|---|---|---|
| 1 | §3 標題 | 寫「還沒開卡的(141 項)」 | §3.1 實有 117 列 + §3.2 實有 28 列 + §3.3 實有 2 列 = 147;扣掉 §3.3 那兩條(是掃描本身的補洞、已有卡)= 145。標題數字與小節標題都要重算 |
| 2 | §3.2 標題 | 寫「非資安但是真 bug(26 項)」 | 實際列了 28 列(編號 7~33 連號,另有一列 18b) |
| 3 | §0「問題累積」表 | 寫「掃到了但還沒開工單的問題 143 項」 | 與 §3 標題的 141、實際的 145 三個數字互不相同 |
| 4 | §7 第 12 項 | STATE 已於 09-15 標註「總表 §6 第 12 項尚未改成已裁,下一任補」 | 該註記至今仍在,這件事已經掛了五天 |
| 5 | §7「已裁決」末段 | 「等全部套件掃完再統一開卡」與「三個例外也不先做」(09-19 裁) | 掃描已於 09-20 收口,這兩條的前提消失了。建議請決策者重新確認 C2 的第 83/84 項(撤銷權杖、清公開站密碼)要不要立刻處理——那兩件不占開發時間 |
| 6 | §3.1 第 34/40/47 項 | 原文仍寫「資料表沒有客戶歸屬欄位、資料庫隔離關閉」 | 已過期(FR-107 為了別的目的補上了)。總表自己在複查段已經警告「開卡前原文必須改寫」,但原文本身還沒改 |
寫清楚免得下一棒誤會已經做過:
| 要什麼 | 去哪 |
|---|---|
| 每一條屬於哪一組、有沒有漏 | classification-matrix.md |
| 每一條的完整技術細節 | README.md §3 |
| 按風險等級排序的視角 | risk-overview.md |
| 現況與已裁決事項 | FR-075/handoff/security-scan-STATE.md |
| 本卡 | CM-1983 |