資安剩餘項目總分類

現況(2026-10-01):本文是 2026-09-26 的分類快照。文中「未修/待裁」的項目後來已全數處理——FR-114 第 8 批 12 組(CM-2211~2220 等)已修並隨 1.21.0 出貨;1.21.1 再修授權讀取(CM-2369)等。最終狀態以 docs/security-report/SUMMARY.md 問題總表為準(已修 206、拆除退場 15、裁定不修 12、SaaS 前必做 1)。以下內文保留當時的分類過程。

資安剩餘項目總分類(CM-2209)

給決策者一次看完、逐類拍板用。裁完後首腦照這份的編號轉成 FR-119 handoff-to-fix-line.md 那種交接格式,開 FR-114 第 8 批,一次修完再出一包(1.21.0b3 暫停 build 就是在等這份,見 FR-114-STATE.md 最末節)。

編號寫法:#N=PM 總報告 docs/security-report/SUMMARY.md 的問題編號;總表 N=資安總表 security-scan-consolidated/README.md §3.1 的項次。兩個都有就都寫。檔:行一律以修正線工作區(fix/security-b1,HEAD 1516d90bc;套件 e758cd6a)為準——那才是第 8 批要改的底版,與主線行號可能差幾行。

1. 一句話結論

還沒修的共 45 項:要決策者裁(丙)8 項、已裁照修(甲)7 項、可直接修(乙)19 項,分 8 組、建議不修只記錄(丁)2 項、已裁暫緩(戊)9 項。

嚴重度 丙 甲 乙 丁 戊 合計
🟠 高 0 1 0 0 3 4
🟡 中 1 4 7 0 5 17
⚪ 低 7 2 12 2 1 24
合計 8 7 19 2 9 45

三個要先知道的:

  • 原本以為還有一百多件沒修,實際是 45 件。 主線那份 PM 總報告只回寫了第 7 批,第 1~6 批修好的 77 件它還寫「未修」;以修正線那份為準,前 145 件真正還掛著的只有 17 件(13 件未修、3 件部分修、1 件 SaaS 前必做),其中 8 件已裁暫緩(戊類)、#101 已裁不修(不列入)。
  • FR-120 這一輪掃出來的 38 項(總表 181~218):已修 11 項(其中 3 項是修正線順手已收、總表還沒標)、1 項非資安,剩 26 項全在這份裡,是第 8 批的主體。
  • 乙類 19 項正常使用看不出任何差別,建議決策者整組一次同意;決策力氣集中在丙類 8 項。丙類只有 1 項是中風險,其餘都是低。

2. 丙類:修了會改變產品行為,要決策者裁(8 項)

現況(2026-10-01):丙類 8 項決策者 09-26 全部裁完並已修(見 handoff-to-fix-line.md 的 8-G/8-F/8-H/8-I/8-C/8-J),隨 1.21.0 出貨。

每項格式:一句白話(誰能做什麼壞事)→ 修了之後誰會碰到什麼變化 → 選項與代價 → 建議。

丙-1 總表 181|低|授權過期只靠每天凌晨一次的排程才轉唯讀

  • 白話:客戶授權到期那一刻不會立刻變唯讀,要等排程(UTC 凌晨 2 點,台灣早上 10 點)跑過才生效;排程如果沒在跑(例如只開即時通訊模式的部署),過期客戶可以一直照常新增、修改資料。
  • 在哪:common/authz/license.py:280 viewer_is_readonly() 只讀資料庫存的狀態欄;排程在 core/scheduler.py:275-323。
  • 修了會改變什麼:過期客戶在到期那一秒就變唯讀,不再有「到期當天還能用到早上 10 點」的寬限。業務或客服若習慣「到期當天還能補照」,會接到客戶「怎麼突然不能改」的電話。
  • 選項:
    • 選項一:讀照時當場重算一次,取較嚴的那個(compute_target_status 是純函式、不查資料庫)——即時生效,代價是上面那個寬限消失。
    • 選項二:維持排程,只補「排程多久沒跑就告警」——行為不變,代價是縫還在,只是看得到。
  • 建議:選項一。授權到期規則本來就寫「到期即唯讀」,排程延遲是實作副作用、不是設計;要寬限應該用授權檔的寬限期欄位明確給,不是靠排程時間差。

丙-2 總表 184|低|首次安裝精靈同時按兩次可能建出兩家公司

  • 白話:安裝精靈「開通」這一步中間沒上鎖,裝機者連點兩次(或兩個人同時送),可能建出兩家公司、兩個管理員帳號。要先持有只印在裝機終端機的設定碼才打得到,實務上幾乎只有裝機者自己連點會踩到。
  • 在哪:app/setup/service/setup_wizard_service.py:37-41(註解宣稱有資料庫唯一約束,但實際沒有)、:167 查開通、:249 建立。
  • 修了會改變什麼:若選加鎖,第二個請求會收到「已開通」錯誤(409),精靈前端要能顯示這個訊息而不是一片空白——前端行為會變。
  • 選項:
    • 選項一:只改註解,寫明「並發窗口存在,因需持有設定碼而接受」——零行為變化。
    • 選項二:加資料庫鎖包住「查開通+建立」,第二個請求排隊、輪到時回 409——要順手確認精靈前端收到 409 的畫面。
  • 建議:選項二。一次連點就留下兩家公司是很難事後清的髒資料,修法只有幾行。

丙-3 總表 187|低|授權過期唯讀有兩條縫

  • 白話:①過期後代理程式的註冊碼照樣能產生(/agents/ 整段豁免唯讀檢查,範圍太寬);②問卷填答走即時通訊那條路時完全不經過唯讀檢查,過期客戶照樣能填問卷。
  • 在哪:common/middleware/license_readonly_mw.py:77(豁免清單);套件 jedi-survey/jedi_survey/app/handler/fill_survey_socketio_handler.py:164。
  • 修了會改變什麼:過期客戶不能再新增代理程式、不能再填問卷。已經裝好的代理程式照常回報(那條是機器對機器,建議保留豁免)。
  • 選項:
    • 選項一:兩縫都補——豁免收窄成「代理程式回報結果那幾支」,問卷即時通道補唯讀檢查。
    • 選項二:只補問卷、代理程式豁免維持——理由是代理程式屬基礎設施,過期時讓客戶還能接回機器方便續約後立刻恢復。
  • 建議:選項一。「過期=唯讀」是對客戶說過的規則,唯讀期間新增機器與填問卷都是寫入。

丙-4 總表 190|低|雲端硬碟授權連結可以轉寄給別人代按

  • 白話:公司 A 的管理員產生一條「連接 Google 雲端硬碟」的授權連結,轉寄給公司 B 的人騙他按同意,B 的 Google 硬碟就被接進 A 公司的帳號。未實測。
  • 在哪:app/cloud_integration/service/google_drive_integration_service.py:96-99 產生 state、:113-116 回呼只看 state 本身。
  • 修了會改變什麼:授權流程必須同一個瀏覽器發起、同一個瀏覽器完成。「管理員產生連結、交給擁有 Google 帳號的 IT 同事去按」這種分工會失效——如果客戶現場真的這樣做,他們會卡住。
  • 選項:
    • 選項一:綁瀏覽器(發起時寫一個 cookie,回呼時比對)——堵住,代價如上。
    • 選項二:不綁、改在回呼成功後寄一封確認信給發起人——分工照舊,事後可察覺。
  • 建議:先問客服/實施有沒有看過「代按」的做法;沒有就選項一。

丙-5 總表 185|中|使用者上傳的檔案整個目錄公開在 /static/ 不用登入(拿不準乙或丙,放丙)

  • 白話:後端把使用者上傳檔案的資料夾設成網站的公開路徑,問卷答案 Excel、意見回饋附件等只要知道路徑就能抓。今天出貨的代理伺服器只轉 /api/1.0 與 /socket.io,所以正式站打不到;但有人為了排錯直接開 8000 埠、或客戶換自己的代理設定,就整包公開。
  • 在哪:core/app_factory.py:95-99(static_folder 指向上傳區,static_url_path='/static')。
  • 修了會改變什麼:我查過修正線 BE、所有套件與前端,沒有任何地方組 /static/... 網址給使用者用(範本下載已在 FR-063.1b 移出 static;問卷答案上傳只是存檔備份,套件 jedi-survey/.../task_survey_route.py:148),所以正常使用看不出差別。
  • 拿不準的原因:只能證明「程式碼裡沒有」,證明不了「沒有客戶或維運手上存著 /static/ 連結在用」(例如舊版信件裡的附件連結、維運腳本)。
  • 修法:static_url_path=None(或設一個不會對外的前綴),寫入路徑不動。
  • 建議:當乙類修(關掉公開路徑),release note 寫一句「/static/ 不再對外提供」;若決策者知道有人在用這種連結,改成丙-5 另議。

丙-6 總表 200|低|批次完成任務的通知信把操作者暱稱原樣塞進信件 HTML

  • 白話:任何帳號把自己的暱稱改成一段 HTML/script,之後他批次完成任務時,收信人開信就看到他塞的內容(可偽造連結、按鈕)。
  • 在哪:app/flow_control/service/job_batch_complete_service.py:95,105、app/flow_control/service/workflow_execution_service.py:1219、app/flow_control/service/project_service.py:776(三處同寫法)。
  • 修了會改變什麼:暱稱改成純文字顯示。暱稱裡本來就有 <、& 的正常使用者(例如「R&D 王小明」),信裡會從「R&D」正確顯示——今天反而可能顯示錯。其餘人看不出差別。
  • 拿不準的原因:信件範本可能有地方刻意讓暱稱帶粗體等 HTML,跳脫後會變成字面顯示。
  • 建議:照修(跳脫),放丙只是因為動到寄出去的信件內容,請決策者知悉。

丙-7 #186/總表 165 剩下那一半|低|AI 儀表板查問卷缺模組授權

  • 白話:沒買問卷模組的客戶,透過 AI 儀表板對 AI 說一句話,照樣能查問卷資料(直接打網址那兩條已補,AI 儀表板這條沒補)。
  • 在哪:di_containers/dashboard_apis/survey.py:20-45(兩支申報);要改套件 jedi-ai-dashboard(jedi_ai_dashboard/app/registry.py 加「需要的模組」申報欄)。
  • 修了會改變什麼:沒買問卷的客戶在 AI 儀表板問問卷相關問題會得到「無權限」而不是資料。要動一支不在 b3 發版清單上的套件(jedi-ai-dashboard),多發一支版。
  • 選項:
    • 選項一:套件加申報欄、兩支問卷查詢掛上——根治,多發一支套件。
    • 選項二:先把這兩支從 AI 可用清單拿掉——不改套件,代價是有買問卷的客戶也暫時不能用 AI 問問卷。
  • 建議:選項一,且與總表 218(同一支套件,AI 儀表板生成端點缺能力點)同一次發。CM-2194 首腦已把這件「轉決策者排批」。

丙-8 總表 218|低|AI 儀表板生成端點只驗商務授權、不驗能力點

  • 白話:角色設定上看不到 AI 儀表板的人(例如「稽核人員」「IT 執行人員」),直接打網址照樣能生成儀表板,而且每用一次要付兩次 AI 服務費。runner 已實測。
  • 在哪:套件 jedi-ai-dashboard/jedi_ai_dashboard/api/routes/ai_dashboard_route.py:103(只有 @require_license);主專案 core/plugins/ai_dashboard.py:52-61。
  • 修了會改變什麼:這些角色直接打網址會被擋(403)。選單本來就看不到,所以正常操作的人看不出差別;會被擋的只有「知道網址、繞過選單」的人,或有人手上書籤存著這個網址。
  • 拿不準的原因:DEV 查到這兩個角色沒有該能力點,但客戶現場的角色設定可能不同——若某客戶把這功能開給了沒勾能力點的角色、靠書籤在用,修完會斷。
  • 建議:照修,與丙-7 同一次發 jedi-ai-dashboard;放丙只為了讓決策者知道「多發一支套件」。

總表 §7「目前真的還要決策者裁的 7 項」(第 8/13/14/18/18b/5/21 項)是方向類待裁,本文不重寫;與本清單無重疊(第 18b 項管的是 §3.2 非資安第 28/29 項;第 21 項管「落地版證據分類停用」,只影響第 6 節 #130 的急迫度),請直接看 §7 那張短清單。


3. 甲類:已裁、照修(7 項)

現況(2026-10-01):甲-1 ✅ 已修(#75,CM-2230/CM-2252);甲-2~4 🗑️ 隨舊線退場(#9/#66/#67,CM-2222);甲-5~7 ✅ 已修(#89 CM-2225、#132 CM-2226、#131 CM-2227),均 1.21.0 出貨。

決策者裁過要修,但還沒有修正卡或卡還沒 Done。

# 編號 嚴重度 一句白話 現況與出處 在哪(修正線)
甲-1 #75(總表 J 組) 🟡 中 打包前端映像檔的腳本與前端三個 CI 設定檔裡,直接寫著一組內部套件倉庫帳密,都進了版本控制 已開卡 CM-1998(Not started);批次規劃第 4 批「清憑證殘留」 BE scripts/build/build_fe_image.sh:49-51;FE .gitlab-ci.yml:21、.gitlab-ci-on-premises.yml、.gitlab-ci-terraform.yml、Dockerfile(NEXUS_AUTH)
甲-2 #9 🟠 高 任何能登入的帳號,在舊版證據分類「預覽證據檔」填一個雲端硬碟檔案編號,就把那個 Google 帳號摸得到的任何檔案抓回來 已裁「舊線整組拿掉」,靠 CM-1849(Not started)拆 見總表 108~111;拆舊線路由 api/routing.py 舊 Drive 分類那段
甲-3 #66 🟡 中 舊線的查結果、查報表、工作清單不檢查專案成員,查不到還會拿呼叫者自己公司的鑰匙去雲端硬碟讀 同上,CM-1849 同上
甲-4 #67 🟡 中 舊線查雲端硬碟的搜尋條件用字串接起來,可被改寫搜尋範圍 同上,CM-1849 同上
甲-5 #89 🟡 中 被稽核的一方在自己交來的證據第一頁寫一段話,就能指揮 AI 把自己歸進全部合規項目 已裁「只做事前預防」(M07 裁定),驗證卡 CM-2061 等 CM-1849 拆完才派;首腦已判「新線也叫同一個容器,退役後幾乎確定仍在」 套件 jedi-evidence-classification/docker/container_entrypoint.py:374
甲-6 #132 ⚪ 低 證據分類程式用到的六個外部套件沒鎖版本、沒校驗碼,上游被掉包會直接裝進產品 已裁「開、校驗碼不能省」(D-b5B-5),同上等 CM-2061 套件 jedi-evidence-classification/docker/requirements.txt、docker/Dockerfile 安裝那一行
甲-7 #131 ⚪ 低 一份做過手腳的壓縮檔能把主機記憶體吃光;逾時後殘留程序繼續燒 AI 額度 已裁「現在修」(D-b5B-6),同上等 CM-2061 套件 jedi_evidence_classification/infra/classifier_container_runner.py:156-186

甲-2~甲-4 三件舊線、甲-5~甲-7 三件分類容器,派工順序被 CM-1849(FR-107.6 舊線退場)卡住(乙-G 的 #129 同樣),而 CM-1849 本身是個跨兩支套件發版+e2e 的大卡。決策者要不要讓第 8 批直接做「刪舊線路由」這一小段、不等整張 CM-1849,是這組唯一的排程問題。


4. 乙類:不改產品行為,可直接修(19 項,分 8 組)

使用者照正常方式用看不出任何差別。建議決策者整組一次同意。

乙-A 補歸屬/成員檢查(4 項,另 1 項修正線已收)

現況:✅ 已修(8-A,CM-2211,1.21.0 出貨)。

這組是什麼病:只驗「有登入」或「是網址上那個專案的人」,沒驗「你要動的東西屬不屬於那個專案/公司」。修法一律用 common.authz 既有守門,不另寫。

編號 嚴重度 一句白話 在哪(修正線)
總表 202 ⚪ 低 同公司任何登入帳號把網址換成別的專案編號,就看得到那個專案這一輪任務的完成數、進行中數 套件 jedi-task-platform/jedi_task_platform/task/app/service/task_execution_service.py:139-141(比照同檔 :49 _check_manager 先解析專案,再呼叫 assert_project_participant)
總表 214 ⚪ 低 人員對帳四處查詢收了公司編號卻沒拿去用,平台管理員身分下會跨所有客戶比對(結果只寫附註、不影響權限) domain/oscal/service/reconciliation/person_reconciler.py:18,34,49,66(比照 organization_reconciler 加 tenant_id 條件)
總表 191 ⚪ 低 驗證雲端硬碟應用程式憑證的端點,總部任何登入帳號都能拿任意一組憑證去試對錯 修正線已收:app/cloud_integration/service/drive_app_credential_verify_service.py verify() 開頭 require_platform_admin()。只剩確認,不必開卡,併入第 7 節不一致
總表 205 🟡 中 還原摘要報告歷史版本時,不檢查那個歷史版本是不是這份報告的——專案成員可以拿別份報告(含別的專案)的內容蓋掉自己這份 app/project_summary_report/service/project_summary_report_history_service.py:66-85(取出 history 後補 history.report_id == report.id,不符回 404;與總表 94 同寫法,總表註記併第 65 項同卡)
總表 203 ⚪ 低 孤兒資料清理如果某次排程沒帶到身分,會把「全部」正常資料判成孤兒整批刪掉(今天排程有帶身分,不會觸發) infra/flow_control/repository/job_binding_orphan_query.py:87,102,125(三處 NOT EXISTS:刪之前先確認「看得到的任務數 > 0」,看不到就中止並記警告)

總表 191 修正線已收、不計入,列在這裡是為了讓修正線知道不要重做。

乙-B 診斷包與紀錄遮罩(4 項,與總表 162「部分修」同組)

現況:✅ 已修(8-B,CM-2212,1.21.0 出貨)。

這組是什麼病:回廠診斷包與伺服器紀錄裡,密碼、登入權杖會以各種寫法原樣留下,遮罩程式只認得其中幾種。要一次修完——總表 162 就是只補一種寫法、其他三件未修的前車之鑑。

編號 嚴重度 一句白話 在哪(修正線)
總表 186 🟡 中 即時通訊服務逐筆記錄封包,登入權杖明文進容器紀錄;診斷包收容器紀錄時沒遮,原樣帶回原廠 core/app_factory.py:189,191(logger=True/engineio_logger=True 改關或降級);infra/support/collector/host_collector.py:136-156、infra/support/collector/staged_collector.py:128-153(兩支都要過 mask_log_lines)
總表 209 🟡 中 診斷包的設定快照遇到跨多行的值只遮第一行,第二行以後的密碼原樣留下(今天出貨的值剛好是單行) infra/support/collector/container_collector.py:94(先遮值再串 KEY=值,或遮罩改成以整個值為單位)
總表 211 ⚪ 低 診斷包收的 API 連線紀錄,網址欄不在遮罩清單,網址帶權杖時原樣收進去 domain/support/entity/diag_bundle.py:30(MASKED_API_LOG_COLUMNS 加 url)
#173/總表 162 剩下三件 🟡 中 證據分類逾時把 AI 金鑰寫進紀錄那條,CM-2193 只補了「KEY=值」一種寫法;其他寫法、資料庫紀錄改走日誌遮罩、打包前統一過一道三件未修 infra/support/diag_masking.py:164-169(遮罩規則補 password='值'、"key": "值" 等寫法);打包前統一過一道

總表 207(寄信失敗把整組寄信設定含密碼寫進紀錄)修正線已修(套件 jedi-notification commit e12287e2,CM-2111),總表還寫未修,見第 7 節。但它當初暴露的「遮罩不認得 password='值'」仍要在上面 diag_masking.py 那列一起補。

乙-C 輸出前跳脫與安全寫法(4 項)

現況:✅ 已修(8-C,CM-2213,1.21.0 出貨)。

這組是什麼病:使用者可控的字,輸出成 Excel/PDF/查詢條件時沒當成「資料」處理。

編號 嚴重度 一句白話 在哪(修正線)
總表 199 ⚪ 低 匯出任務 Excel 時,欄位以 = + - @ 開頭會被 Excel 當公式,打開的人按了「啟用內容」就在他電腦上執行 app/flow_control/service/job_import_service.py:135-180 export_excel(沿用總表 §4 🅶 組那支「開頭是公式字元就前置單引號」的中和函式,不要寫第四份)
總表 204 🟡 中 摘要報告匯出 PDF 時,圖片白名單放行了 SVG,SVG 可以指向內部網址讓伺服器去抓(繞過 CM-892 的防護) api/project_summary_report/routes/project_summary_report_route.py:42-49(data:image/svg+xml 排除)與 :166 write_pdf(url_fetcher=拒絕一切外部網址),兩處都做
總表 197 ⚪ 低 依名稱找雲端資料夾時只跳脫單引號、沒跳脫反斜線(與總表 110 同型,未實測) infra/cloud_integration/google_drive/google_drive_api_client.py:121(先跳脫 \ 再跳脫 ')
總表 196 ⚪ 低 雲端硬碟通知的 token 比對不是固定時間比對,理論上可用時間差猜 app/cloud_integration/service/google_drive_webhook_service.py:94(!= 改 hmac.compare_digest)

乙-D 維運腳本與診斷包路徑(3 項)

現況:✅ 已修(8-D,CM-2214,1.21.0 出貨)。

這組是什麼病:維運指令與出貨主機的預先蒐集,信任了容器內或索引檔裡的路徑。前提都是「已經能動容器內部的人」,但後果是 root 被騙寫到任意地方。

編號 嚴重度 一句白話 在哪(修正線)
總表 208 🟡 中 系統診斷指令用猜得到的名字建暫存資料夾、不檢查是不是捷徑,容器內一般權限的人可預放捷徑騙 root 寫到別處 scripts/installer/guidant diag 段(:720、:775 附近 mkdir -p "$stage_host";報告寫的 :700-708 已漂移)改 mktemp -d,或建立前檢查不存在且非符號連結
總表 210 ⚪ 低 出貨主機預先蒐集只照索引檔的路徑讀檔,服務名稱沒驗證,可塞 ../ 跳出暫存目錄 infra/support/collector/staged_collector.py:90,140(服務名稱白名單,讀檔前 realpath 檢查在暫存目錄內)
總表 206 ⚪ 低 匯出診斷包時,起始時間帶時區、結束時間不帶,比較時程式當掉回 500 app/support/service/diag_bundle_export_service.py:76 _resolve_window(兩邊統一轉成帶時區)

乙-E 首次安裝精靈錯誤處理(1 項)

現況:✅ 已修(8-E,CM-2215,1.21.0 出貨)。

編號 嚴重度 一句白話 在哪(修正線)
總表 183 ⚪ 低 安裝精靈設定碼欄位塞中文或特殊字元,伺服器回 500 並寫一筆錯誤紀錄(不會放行),任何人能灌假警報淹掉真的錯誤 common/setup/setup_token.py:92(比對前只允許英數字,或兩邊 .encode() 再比);呼叫點 api/setup/routes/setup_route.py:70、:97 不用改

乙-F 刪沒人用的死碼(1 項)

現況:🗑️ 已拆除(M06-16 備用服務由 8-E 拆掉,CM-2215)。

編號 嚴重度 一句白話 在哪(修正線)
#118(M06-14+M06-16) ⚪ 低 三支接收檔案路徑的程式直接開檔讀寫;兩組接好但沒人用的備用服務沒有權限檢查——現在無害只因沒人用 一半已收:M06-14 三支(save_bpmn_to_file/export_xml/import_xml)已隨套件 commit 4a416ece(CM-2059)刪除。剩 M06-16:di_containers/flow_engine/workflow_excution_containers.py:4,114-117 的 JobExecutionService provider 全庫零引用,拆掉 import 與 provider 即可(同檔 ElementVariableService 有人用,保留)

總表 215(解析工作單新增規則一律允許)修正線已收(scripts/sql/2026-09-25-fr114-ap-ar-parse-jobs-rls-fix.sql:21-26,58-63,CM-2195),只剩出貨基線重產時帶到(CM-2197 已列),不計入。

乙-G 證據分類刪除殘留(1 項,與甲-5~7 同一張驗證卡 CM-2061)

現況:✅ 已修(#129,CM-2227,1.21.0 出貨)。

編號 嚴重度 一句白話 在哪(修正線)
#129(M07-6) ⚪ 低 使用者按「刪除整批」後,判定結果與分類紀錄仍永久留在後端主機上——使用者以為刪乾淨了其實沒有(要主機權限才看得到,不是越權) 套件 jedi_evidence_classification/app/service/evidence_batch_service.py:1417-1427(刪整批時連同 classifier_container_runner.py:85-89 建的工作目錄一起清)

乙-H 刪檔順序(1 項)

現況:✅ 已修(總表 217,CM-2228,套件 5ec9b617,1.21.0 出貨)。

編號 嚴重度 一句白話 在哪(修正線)
總表 217 🟡 中 刪檔時先刪硬碟上的實體檔、再刪資料庫紀錄;紀錄被資料庫擋下時檔案已經沒了,回應卻是「成功」 修正線已擋掉主要打法:刪除入口 upload_file_route.py:113 掛了歸屬檢查、原廠共用檔(storage_scope='system')刪除一律擋(core/plugins/file_upload.py:240-253)。剩順序:套件 jedi-file-upload/.../infra/adapter/minio/minio_adapter.py:129-138(以及 :144-176 批次刪)改成先刪紀錄、成功才刪實體檔。總表註記併第 37 項同卡;驗收加「一般帳號刪原廠共用檔要失敗且實體檔仍在」

乙類合計:乙-A 4+乙-B 4+乙-C 4+乙-D 3+乙-E 1+乙-F 1+乙-G 1+乙-H 1=19 項。中風險 7 項(總表 205/186/209/162/204/208/217),其餘低。


5. 丁類:建議不修或只記錄(2 項)

現況(2026-10-01):總表 213 🗑️ 已拆除(CM-2373,1.21.1);總表 195 🚫 裁定不修。

編號 嚴重度 理由 什麼時候要回頭修
總表 213 ⚪ 低 即時通知有一個頻道不驗身分、任何人能加入任意房間。但伺服器端沒有往這個頻道送資料,前端唯一會用到的元件 ProcessDiscussBox.vue 在畫面上沒被引用,面板判不成立 ProcessDiscussBox.vue 被接回畫面之前,先在 app/notification/handler/notification_socketio_handler.py:19,34,43 補身分驗證
總表 195 ⚪ 低 雲端硬碟通知的註解說有去除重複通知,實際沒有。後果只是同一個變更可能被處理兩次;同步處理本身是冪等的(重複匯入同一檔會命中既有對應) 若日後出現「同一份證據被匯入兩次」的客訴,或同步處理改成非冪等時

總表 201「查不到專案就放行」是決策者 09-26 裁定、CM-2208 已照做,不列在這裡;CM-2208 runner 實查 DEV 54,267 個流程實例全部查得回專案,實務上走不到那一支。


6. 戊類:已裁暫緩(9 項)

現況(2026-10-01):#23 ✅ 已修(CM-2271+CM-2369)、#104 ✅ 已修(CM-2271)、#24 ✅ 已修(12 張補齊,餘 1 張屬平台層設定)、#105 🕓 SaaS 前必做、#98/#91 🚫 裁定不修、#99 📋 已裁記錄不修、總表 193 🚫 裁定不修、#130 ✅ 已修(CM-2223)。

只列,不展開。

編號 嚴重度 一句話 裁定
#23(M18-8) 🟠 高 被停權客戶用子單位帳號,就能刪掉母公司頭上的停權紀錄自己復權 第 6 批「資料庫最後一道牆」:程式面先修、測過一版、決策者裁「開牆」才開卡(FR-114.../dispatch-plan.md §4);是 #104 的直接後果
#104(M03-7) 🟠 高 資料庫隔離規則方向寫反:子單位看得到、改得到、刪得到母單位資料(出貨基線共 11 條) 同上
#24(M20-1) 🟠 高 13 張標有客戶歸屬的表,資料庫隔離牆沒真正生效(部分修) 同上
#105(M20-5) 🟡 中 走 SaaS 時合規文件那塊沒有最後一道防線 🕓 SaaS 上線前必做
#98(M17-7) 🟡 中 安裝程式每套都種同一組原廠超級管理員密碼、不強制首次登入改 已裁「維持記錄、暫不調整」
#99(M18-7) 🟡 中 開發環境私鑰簽的授權檔,正式環境也認 已裁「等正式簽發站建好一併處理」
#91(M08-4) 🟡 中 解鎖碼帳本被改成亂碼時只記高等級警示、不拒絕(部分修) 已裁「原廠有重簽流程後再收緊」
總表 193 🟡 中 雲端硬碟資料夾(含根資料夾)分享設定是「知道連結的任何人都能編輯」,根資料夾連結任何登入帳號拿得到 決策者 09-26:POC 階段暫緩(要綁客戶 Workspace 網域,短期不綁)
#130(M07-7) ⚪ 低 AI 服務金鑰放在分類程式的啟動參數上,同主機任何帳號讀得到 已裁「可以緩」(D-b5B-6);前提是落地版刻意沒裝分類執行環境,只影響開發機——哪天落地版要開自動分類(§7 第 21 項),要先修

7. 三份紀錄不一致清單(給修正線合回報告時用)

7-1 主線 PM 報告 vs 修正線 PM 報告(#1~145):兩邊狀態不同的共 94 件。

  • 77 件主線寫「未修」、修正線寫「已修」——以修正線為準,合回時整批覆蓋即可。
  • 6 件主線寫「裁定刪除」、修正線寫「已修」;5 件主線寫「部分修」、修正線寫「已修」;1 件主線寫「裁定做法」、修正線寫「已修」;1 件主線「裁定拆除」、修正線「已修」——同上,以修正線為準。
  • 要人看一眼的 4 件:
    • #91:主線「未修」、修正線「⚠️ 部分修(毀損只記警示不拒絕)」。
    • #101:主線「未修」、修正線「⚠️ 部分修(lock 已入版控;https 裁不修)」。
    • #124:主線「未修」、修正線「🚫 裁定不修(比照 #101)」。
    • #109:兩邊都是「裁定退役」,只是格式不同,不用處理。

7-2 主線 PM 報告 #146~198(修正線那份沒有這段):主線寫未修/部分修共 11 件,實際:

# 主線寫 實際 依據
#169 #170 #182 ⬜ 未修 ✅ 已修 CM-2191 Done(總表 155~157 已標)
#171 ⬜ 未修 ✅ 已修 修正線 job_force_start_service.py:136-138(CM-2113 補歸屬、a3fe63b03)
#183 ⬜ 未修 ✅ 已修 CM-2191 Done(總表 158)
#184 ⬜ 未修 ✅ 已修 CM-2148 修正待驗證(a3fe63b03),總表 160 還寫未修
#172 ⬜ 未修 ✅ 已修 CM-2192 Done(總表 161 已標)
#186 ⬜ 未修 🟡 部分修 CM-2194 Done 入口一、三;入口二=本文丙-8
#173 ⬜ 未修 🟡 部分修 CM-2193 只補一種寫法;剩下=本文乙-B
#161 🟡 部分修 🟡 部分修(檔案下載擁有者另評估) 修正線 core/plugins/file_upload.py:191-212 程序書檔案已有讀寫歸屬檢查;建議首腦實測一次再改「已修」
#179 🟡 部分修 🟡 部分修(決策者選 A) 決策者已裁只拿掉 email 與設備 IP,這就是終局,建議改「✅ 已修(依裁定範圍)」

7-3 主線模組頁:M06-flow-engine.md 第 17~22 條(=#169~#171、#182~#184)全標未修,實際全修(見上表);第 14 條(#118 前半)標未修,實際已隨 4a416ece 刪除。

7-4 資安總表 §3.1(修正線是照 PM 報告編號派工,不回寫總表):

項次 總表寫 實際 依據
118、119 未標狀態 ✅ 已修 CM-2041 Done;修正線 PM 報告 #64 已修
122 未標狀態 ✅ 已修 修正線 ssp_docx_generator.py:62 render(context, autoescape=True);PM 報告 #102 已修
126 未標狀態 ✅ 已修 修正線 PM 報告 #151 已修(CM-2055)
159 未標狀態 ✅ 已修 同 #171
160 未標狀態 ✅ 已修 同 #184(CM-2148 修正待驗證)
191 未標狀態 ✅ 已修 修正線 drive_app_credential_verify_service.py verify() 開頭 require_platform_admin()
207 未標狀態 ✅ 已修 套件 jedi-notification e12287e2(CM-2111);主線套件源碼 smtp_mail_adapter.py:52,57 仍是舊寫法,發版後才進出貨
215 未標狀態 ✅ 已修 CM-2195 migration 已改 INSERT 規則
1~117 大部分 多半未維護 以修正線 PM 報告為準 修正線照 PM 報告編號派工、不回寫總表(CM-2199 已回寫第 7 批,第 1~6 批未回寫)

7-5 總表 §7 待裁清單:短清單下方註記「第 51 項已裁、FR-114 開卡中,卡號待回填」→ 卡號是 CM-2208(Done,1516d90bc)。


8. 附:怎麼核對的

段 範圍 用的來源 怎麼判
段一 PM 報告 #1~145 修正線 .claude/worktrees/wt-fix-security/docs/security-report/SUMMARY.md 問題總表+M07/M06/M10 模組頁 狀態欄非「已修」的全部列出(13 件未修、3 件部分修、1 件 SaaS 前必做、9 件裁定不修/退役/刪除——其中 #118 裁定刪除但只刪了一半,列乙-F),逐件對照裁定;#118 另開套件 git log 確認前半已刪;#101、#124 已裁不修、不列入
段二 PM 報告 #146~198(總表 118~180) 主線 SUMMARY 為起點;第 7 批卡清單 FR-114-2609-security-fix-dispatch/cards/made-b7*.json(35 張)逐張 notion_case.py get 查狀態 33 張 Done、發版卡 CM-2197 與母卡 CM-2170 Not started;主線寫未修但有 Done 卡涵蓋的以卡為準;拿不準的開修正線程式碼核對(job_force_start_service.py、ssp_docx_generator.py)
段三 總表 181~218 總表 §3.1、scan-U*.md、handoff-acceptance-brief.md、§7 已裁記帳 已修 11 項:182/188/192/194/198/201/212/216(Notion 卡 Done)+191/207/215(修正線程式碼已收、總表未標);189 為非資安(§3.2);其餘 26 項逐項開修正線檔核對行號是否漂移
裁定 — 修正線 SUMMARY「已裁定」各列+主線 SUMMARY「這一輪新裁定的十九件」+總表 §7(刪除線與已裁記帳)+FR-114-STATE.md 最末三節+卡片 CM-2061/CM-2194 回寫 裁過的照登,沒重判

判「乙還是丙」用的準則:使用者照正常方式用(走選單、不改網址、不繞路)是否看得到差別。會被擋的只有「繞過選單直打網址」的,算乙;正常流程會變(寬限期消失、分工斷掉、錯誤訊息出現、多發一支套件)的算丙。拿不準一律丙並寫理由(丙-5、丙-6、丙-8)。

打折處:

  • 行號以修正線 HEAD 1516d90bc/套件 e758cd6a 為準,第 8 批開工前若修正線又前進,runner 要照卡上「先 grep 驗行號」的紀律重新對。
  • 「/static/ 沒有任何地方在用」只查了程式碼(BE、全部套件、前端 src/),沒查客戶端或維運手上存的舊連結——所以丙-5 放丙。
  • 丁-3(總表 201 查不到專案)的「全部查得回」是 DEV 的數字,STG/POC 沒查(唯讀可查,但本卡不必要)。