---
title: 任務與成員管理
eyebrow: Guidant AI 資安檢視 · 模組報告
h1: 任務與成員管理（jedi-task-platform）
lede: 管「誰是這個專案的人、哪個任務派給誰」的那一塊。**這一頁要講兩件事**：查到的 12 個問題（多數是「同一家公司裡，不是這個專案的人也看得到、也動得了」），以及**我們主動停在第三輪、任務與專案兩整塊功能完全沒碰過**的理由與代價。
---

## 這塊在產品裡做什麼

產品裡每一個稽核專案都有成員：管理者、稽核員、審核者、只能看的人。每個任務（例如「檢查某一條控制項」）會指派給其中一位成員去做。這一塊管的就是這些事——**誰是成員、他是什麼角色、哪個任務派給誰、任務怎麼啟動、任務底下的留言**。

::: grid2
::: {.card .plain}
#### 它平常在做什麼
1. 記錄每個專案有哪些成員、各自是什麼角色
2. 把任務指派給人、記錄誰是審核者
3. 讓別的功能來問「這個人在這個專案能做什麼」
:::
::: {.card .warn}
#### 為什麼它是敏感目標
**系統每次要判斷「你在這個專案能做什麼」，最後都是來查它管的那幾張表。**

其他模組查到的「只驗登入、不檢查歸屬」問題，修法幾乎都是「補一行去問這一塊」——**如果這一塊自己有洞，前面所有修法都建在沙上。**
:::
:::

---

## 檢視軌跡

**檢視期間**：2026-09-14 ～ 2026-09-15｜**範圍**：109 個檔案（模組本體 74、接線 35）｜**共 3 輪（原訂 7 輪，做完三輪主動停止）**

> **未檢視的範圍**：這一塊的模組本體現有 193 個檔案，其中約 30 個是零內容的橋接檔。**查過 74 個，還有約 86 個沒查**——沒查的部分裡，**任務與專案這兩整塊功能完全沒有碰過**。

> **原始技術報告**放在需求中心的 [FR-095 站](https://guidantai-feature-doc.jedicotech.com/FR-095-2609-task-platform-security-scan/)，檔名見下表最後一欄。那裡有每一輪的完整技術細節、檔案清單與逐條推理，供需要深究或稽核抽查時查閱。

| 輪次 | 查什麼 | 檔數 | 覆核投票 | 結果 | 原始報告檔名 |
|---|---|---:|---|---|---|
| **P1** | 專案成員怎麼加、怎麼移除、角色怎麼指派，以及把關的那道檢查長什麼樣 | 39 | 12 票全投完，**四條全部三票一致** | 通過 2 條，**人工另外查出 3 條**，登記 5 條 | `scan-P1-participant-membership-and-guard` |
| **H1** | 我們主系統這端怎麼建專案、同步成員、把這塊接上來 | 35 | 24 票全投完，**八條全部三票一致** | 通過 4 條新問題（另 3 條是舊案重複），登記 3 條資安＋1 條程式錯誤 | `scan-H1-project-crud-and-wiring` |
| **P2** | 任務怎麼指派、六張成員相關資料表怎麼被讀寫 | 35 | 6 票全投完，**兩條全部三票一致** | 通過 2 條，**人工另外查出 4 條**，登記 4 條資安＋3 條程式錯誤 | `scan-P2-task-assignee-and-participant-tables` |

::: {.callout .warn}
**第一輪（P1）的完成紀錄標成「不完整」，但那不是投票失敗**

三輪裡只有 P1 這一張紀錄寫著「不完整」。**實際情況是票全投完了**——四個疑點各三票、共 12 票，四條全部三票一致通過。

標成不完整的原因是**存檔時的格式問題**：寫報告的時候多帶了一層目錄路徑，系統對不上就把其中兩條退了回去。**是存檔出錯，不是查證沒做。**

這正是[檢視方法](GUIDE-01-method-and-tools.html#stamp)那一章講的三種「沒跑完」裡的第三種——看到「不完整」要先分清楚是哪一種，不能一律當白跑。統籌者逐條開檔核對過這一輪的全部結論，**沒有改判任何一條**。
:::

::: {.callout .crit}
**三輪之後我們主動停手——這一節請務必讀完**

原本規劃七輪。做完三輪，**由負責統籌的人建議、決策者在 2026-09-15 採納，決定不再往下查。**

**理由**：剩下四輪要問的問題，前三輪已經答完了。**同一個根本原因第三次出現**——所有模組共用的那段取資料的程式有一條規則「查詢條件有填才過濾，全部沒填就不過濾」，於是「送一個空白查詢＝回整張表」。這條已經在檔案下載、成員名冊、任務指派三個地方各爆一次。**再查下去只會第四次撞到同一件事。**

同樣的時間拿去查**從來沒碰過的模組**，價值比較高。

**被排除的選項是「照原計畫跑完七輪」**——排除的理由是再查下去收穫遞減，**不是範圍畫錯**。如果這一塊日後有大改動，或修正時發現前三輪沒涵蓋到的形狀，這個決定可以重新檢討。

**這不是這一塊自己放棄。** 2026-09-20 全站做了同一個判斷——檢視工具本身不可靠，繼續往下掃不划算，整輪改成「針對已經發現的修」（見[總報告首頁](index.html)）。**這一塊三輪就停，是同一個決策邏輯的第一次體現**：不是遇到困難就縮手，是每次都先問「再投一輪，拿得回相稱的東西嗎」。
:::

::: {.callout .warn}
**停手的代價，必須講清楚**

**不能說「這一塊查過了」**，只能說「查了最關鍵的三輪」。

**沒查的部分裡，任務與專案這兩整塊功能完全沒有碰過。** 如果那裡有「別種類型」的問題（不是那個共用的根本原因），這次不會被發現。

這是日誌那一塊換來的教訓：**能預測的是「同一類問題還會不會再出現」，不能預測的是「別類問題存不存在」**。當時判斷那一輪把關紮實、預期零到一條，結果查出一條高風險——而且問題出在匯出功能上，跟把關完全無關。

停手是有理由的取捨，**不是「這裡沒問題」。**
:::

---

## 問題一覽

::: {.callout .ok}
**以下各條依現行程式確認**

第 1～12 條是本模組四輪查出的，第 20～22 條是主系統掃描另外查出的；各條修了沒有以表中「狀態」欄為準。其中 3 條經決策者裁定為「整段刪除」、1 條裁定「整頁拆除」，理由寫在各條的展開段。

**跨客戶的部分已經被資料庫擋住**——六張成員相關的資料表現在都開著客戶資料隔離。**剩下的問題幾乎全部是「同一家公司內部」**：不是這個專案的人，看得到、甚至動得了別人專案的東西。唯一例外是第 4 條裡的稽核團隊名單那支——它底下的資料表沒有客戶隔離，跨客戶也打得到。
:::

**排序按風險，同風險的同一類排在一起。**「出事會怎樣」那欄講的是**業務影響**——誰受影響、損失什麼，不是技術現象。

| # | 問題 | 風險 | 分類 | 出事會怎樣（誰受影響） | 怎麼修 | 狀態 |
|---|---|---|---|---|---|---|
| **4** | **稽核輪次與稽核結果**：同公司裡不是這個專案的人，在網址上換成別人的專案編號，就看到那個專案的稽核輪次——**以及稽核判定、風險評等、改善計畫與負責人姓名** | 🟠 高 | 只驗登入、不檢查歸屬 | 原本只看得到輪次名稱、狀態、起訖日與人員；[稽核輪次管理那塊](M12-compliance-audit.html)查完後確認**同一個形狀有十支讀取入口**，看得到的是別人專案的稽核判定與改善計畫，比輪次清單機密得多，所以升為高。其中稽核團隊名單那支（含 Email、電話）**跨客戶也打得到** | 開頭先由專案編號查出專案，再呼叫現成的成員檢查。十支都已補（八支 CM-2037；稽核計畫選單、稽核計畫儀表板與團隊名單「查不到輪次就回找不到」由 CM-2172 補，1.21.0 出貨） | ✅ **已修（CM-2037）** |
| **1** | **專案成員名冊**：同一家公司裡任何登入的人，送一個連專案編號都不填的空白查詢，一次拿到公司內全部專案的成員名冊 | 🟡 中 | 只驗登入、不檢查歸屬 | **連「要查哪個專案」都不必知道**，一次拿到公司內所有專案的編號、誰是管理者、每位成員的登入帳號與暱稱（開發環境實測是兩千多筆）。跨客戶已被資料庫擋住，但**在同一家公司內這就是一份完整名冊**——外洩的登入帳號可以拿去做針對性的密碼攻擊，「誰是哪個專案的管理者」是挑社交工程目標用的名單 | 兩支查詢開頭都補上「你是不是這個專案的成員」，專案編號改成必填、沒帶就拒絕 | ✅ **已修（CM-2036）** |
| **2** | **專案裡的群組與控制項成員配置**：同公司裡不是這個專案的人，在網址上換一個編號送出查詢，就讀到別人專案的人員配置 | 🟡 中 | 只驗登入、不檢查歸屬 | **用連續猜測的編號，就能讀走同公司任何一個專案在群組層與控制項層的完整人員配置**，而且會順便把專案層的成員一起撈出來——一次請求拿到一個專案三個層級的人員與角色全貌 | 兩支查詢補上同一道成員檢查＋專案編號必填 | ✅ **已修（CM-2036）** |
| **3** | **專案摘要報告（稽核結論）**：同公司裡不是這個專案的人，直接開報告就讀得到結論全文，包含歷史版本 | 🟡 中 | 只驗登入、不檢查歸屬 | **不是這個專案的同事也能讀走稽核結論全文**——歷史版本常保留後來被刪掉的稽核發現。同一個檔案的新增、修改、刪除、還原版本都有檢查，**只有讀取漏掉** | 五支讀取功能開頭補上同檔已有的成員檢查；**清單頁不能改必填**（它本來就要列出「我看得到的所有報告」），改成只列出你有參與的專案的報告 | ✅ **已修（CM-2037）** |
| **5** | **任務指派清單**：同公司裡任何登入的人，送一個空白查詢，一次拿到公司內全部的任務指派紀錄 | 🟡 中 | 只驗登入、不檢查歸屬 | **一次拿到一萬多筆任務指派**，每筆含專案、任務、被指派人的登入帳號與暱稱、誰是審核者。**也可以只帶一個人的編號，反查這個人手上有哪些任務，鎖定目標** | 專案編號或任務編號二擇一必填、兩個都沒帶直接拒絕；帶任務編號的由任務反查專案，再檢查成員身分 | ✅ **已修（CM-2036）** |
| **6** | **指派任務**：小明自己開一個新專案（他自動是管理者），送出指派時「專案填自己的、任務填別人專案的」，系統只查他是不是自己那個專案的管理者，就放行 | 🟡 中 | 只驗登入、不檢查歸屬 | **任何人只要自己開一個專案，就能把別人專案的任務登記成自己的指派**。更麻煩的是主系統靠這張表反查任務屬於哪個專案，**塞一筆假紀錄可能騙過那道判斷，進而改動別人專案的任務狀態** | **已修（FR-114.1-3＋FR-114.6-0a）**：寫入前做兩道比對，任一不符就拒絕（回「找不到」避免被當探測工具）：①被指派的人必須是該專案成員；②**任務本身必須屬於填進來的專案**——由系統唯一的「任務屬於哪個專案」判斷反查（走稽核輪次），不看任務指派表自己。開發環境既有 166 筆有任務的指派，用這個判斷解出的專案與紀錄上的專案全部一致，正常指派不受影響。 | ✅ **已修**（FR-114 CM-2071，套件 commit `ef9a313b`／BE commit `fccfe4db7`） |
| **20** | **專案摘要報告匯出 PDF**：插圖的白名單放行了 SVG 格式，SVG 裡可以指定網址，產 PDF 的程式會照著去抓 | 🟡 中 | 外部送什麼就收什麼 | **能編輯摘要報告的人，可以讓我們的伺服器替他去連公司內網的其他機器**，把內網服務的回應印進 PDF 帶走。先前為了擋這件事建的防護，在這裡被繞過了；統籌者在自己機器上重現成功 | 兩道都做：白名單拿掉 SVG；產 PDF 時一律拒絕抓任何外部網址 | ✅ **已修，1.21.0 出貨**（8-C，CM-2213，commit `a5804a990`／`bde8f9d16`）。主系統掃描查出 |
| **21** | **專案摘要報告還原歷史版本**：不檢查那個歷史版本是不是這份報告的 | 🟡 中 | 只驗登入、不檢查歸屬 | 專案成員指定**別份報告的歷史版本編號**，就能把別人報告的內容蓋進自己這份，或把自己專案的報告內容換成別專案的稽核結論——**稽核文件被摻進不相干的內容**。第 3 條修好的是「讀」，「還原」這個動作沒改到 | 取出歷史版本後比對它屬於哪份報告，不符就回「找不到」（與問卷同一種修法） | ✅ **已修，1.21.0 出貨**（8-A，CM-2211，commit `fe928859f`）。主系統掃描查出 |
| **7** | **群組層的成員管理**：系統啟動時漏接了一條線，這支負責新增／修改／刪除群組成員的程式整支完全不檢查權限 | 🟡 中 | 身分驗證缺失 | **它不報錯也不留紀錄，就只是安靜地全部放行。** 更要緊的是：**這張表被系統拿來算「哪些專案我看得到」——塞一筆進去，那個人就多看到一個專案。** 目前沒有對外入口打得到這三個寫入功能，但哪天有人幫它加一個入口，就是完全開放 | **裁定刪除**：新增、修改、刪除三個功能整段拿掉（全系統已確認零使用）；查詢那支留著給 AI 儀表板呼叫；資料表保留。已於 FR-114.3-2 實際刪除這三支寫入功能與相關 import，查詢功能與資料表原樣保留 | 🗑️ **已裁定刪除，已刪除**（FR-114.3-2，1.21.0 出貨） |
| **8** | **流程參與者管理**：一整組從沒啟用過的功能——把關的檢查寫在「提前結束」後面永遠跑不到、資料表在開發環境是 0 筆、修改與刪除一定出錯 | 🟡 中 | 身分驗證缺失 | 現在擋住它的**不是那道檢查，是它本身就壞著**。**哪天有人很自然地把壞掉的地方修好，這裡就會從「程式出錯」變成真正的權限繞過**——而修的人會覺得自己在修 bug，不會知道那個 bug 正是唯一的守門員 | **裁定刪除**：新增、修改、刪除三個功能整段拿掉；**資料表與回傳格式的定義要留著**（別的地方在用）。已於 FR-114.3-2 實際刪除這三支寫入功能，連同那段「提前結束、永遠跑不到」的壞掉檢查一起移除 | 🗑️ **已裁定刪除，已刪除**（FR-114.3-2，1.21.0 出貨） |
| **9** | **「送空白查詢就回整張表」是所有模組共用的底層行為**——第 1、5 條背後的同一個病灶 | 🟡 中 | 要先做產品決策 | **已經在三個不同模組各放大成一次大量外洩**（檔案清單、成員名冊、任務指派）。不在底層處理，**同型問題會在下一支新功能再長出來一次** | **決策者已裁定**：底層不動，只修有洞的那 3 支（就是第 1、5 條的修法）。**反悔條件：新功能第四次撞到同一件事，就改底層** | ✅ **已裁定做法**（逐支補，底層不動） |
| **10** | **寫入成員時只驗專案、不驗群組與控制項**：填進來的群組或控制項可能根本不屬於那個專案，系統不比對 | ⚪ 低 | 只驗登入、不檢查歸屬 | 要先是某個專案的管理者才做得到，門檻比較高。但**寫入型的越權比讀取型更難清理乾淨**——已經寫進資料庫的錯誤資料要另外清除 | **裁定退役（FR-114.6-0b，決策者 2026-09-25 裁）**：這組功能寫不進去也讀不出來——後端把文字編號換成數字編號的那支程式是空殼（寫死回傳 0），按儲存一律被擋；畫面上的成員清單則寫死是空的。半年沒人發現，代表現行流程沒有在用群組／控制項層的管理者。已把寫入與讀取共四支網址、前端兩頁的「成員」按鈕與側欄一起拿掉，入口消失、這條也跟著消失。兩張資料表先留著（「我參與哪些專案」的查詢還在讀），下一版再清。 | 🗑️ **裁定退役（FR-114 CM-2072，BE commit `390b13908`，套件 jedi-task-platform commit `f1fa23c1`／FE commit `2cb7fb4`）** |
| **11** | **合規資源庫**：同一家公司內，有「修改資源庫」權限的人可以改掉別人建的那一份資源庫的控制項清單 | ⚪ 低 | 只驗登入、不檢查歸屬 | 同公司內部的資料被別的同事改掉——**拿這份資源庫開專案的人，以為在稽核範圍內的控制項其實沒被評估**。只限同一家公司內，且要有修改資源庫的權限 | 改之前先確認這份資源庫是不是你自己建的；不是就拒絕 | ✅ **已修（CM-2040）** |
| **12** | **更新成員資料**：撈不到既有紀錄時，整段跳過管理者檢查 | ⚪ 低 | 身分驗證缺失 | 目前靠後面另一道檢查頂住，實際結果是「查無資料」而不是「未經授權的寫入」。但這是**靠一道檢查擋另一個缺口**的結構——哪天有人把它改成「查不到就當新增」，這道把關會靜默消失 | **已修（FR-114.1-3）**：改成撈不到既有紀錄就直接拒絕（回「找不到」），不再跳過管理者檢查往下走；寫法照抄同一支檔案的刪除功能。修的是結構而非當下可利用的漏洞——原本靠下游一道檢查頂住，那道一旦改成 upsert 就會靜默失效。 | ✅ **已修** |
| **22** | **證據蒐集的執行進度**：同一家公司任何人把網址換成別的專案，就看得到那個專案這一輪任務的完成數 | ⚪ 低 | 只驗登入、不檢查歸屬 | 同公司裡不是這個專案的人，看得到別人專案的稽核進度（完成幾個、還差幾個）。只是數字、不含內容 | 比照同一支程式裡隔壁那個功能，先確認專案、再確認你是成員 | ✅ **已修，1.21.0 出貨**（8-A，CM-2211，commit `fe928859f`）。主系統掃描查出 |

### 另外還查出 7 件程式錯誤（不是資安問題）

這幾件跟被入侵無關，但確實是程式寫錯了，值得順手修掉。**其中前兩件會直接誤導修正工作，特別重要**：

| # | 是什麼 | 為什麼值得一提 |
|---|---|---|
| **13** | 三支成員管理程式各有一支「用編號查資料」的功能，永遠回傳固定的空結果 | 🔴 **補上權限檢查之後，如果拿這條路徑去測試，會看到「通過了」的假象**——實際上是因為查詢本身就查不到任何東西。這三支隨第 7、8、18 條的刪除一併零使用，可以一起拿掉；若決定留著，**驗收時絕對不能走這條路徑測** |
| **14** | 有一個「快速設定」畫面，按下去顯示成功但一筆都沒存 | ✅ **已修（FR-114.3-5）**：刪除這個獨立畫面的兩個入口網址與畫面元件（翻譯檔因跨頁共用保留）。 系統裡有**兩個**快速設定：專案規劃頁那個已經改走新做法、會正常存；**另一個獨立畫面還打著舊做法，而系統內部已經關掉、固定回空**——畫面跳出成功提示，實際什麼都沒寫入。**那一頁有兩個入口網址（一般版與稽核計畫版），兩個都沒有任何按鈕或連結導過去，只有手打網址才進得去。** 決策者裁定**整頁拆除，兩個入口都要拆** |
| **15** | 有一支防止任務指派寫入異常的資料庫檢查，從來沒有真的掛上去 | **比原本想的更難修**：那支檢查要讀的三個欄位在那張表上根本不存在，直接補掛上去第一筆寫入就會出錯（該表已有一萬多筆資料）。**這道檢查要不要留，留到修正工單時再定** |
| **16** | 另有一支資料庫的「你看不看得到這個任務」的判斷，讀一個不存在的欄位 | 與第 15 條同型——**寫好了但沒掛上任何規則，所以現在不會出錯；哪天掛上去，一呼叫就爆** |
| **17** | 專案啟動時的成員同步刻意繞過把關、直接寫資料 | 這件事本身合理（建專案的人就是管理者）。主系統有**一處**不經把關直接寫成員表，登記備查（另外四處都靠上一層擋住了） |
| **18** | 四支任務指派相關功能沒有對外入口、也沒有任何把關 | ✅ **已修（FR-114.3-2）**：**裁定刪除其中三支**（其中一支是被新版取代後留下的舊版，不是「還沒接」）；第四支「依專案刪掉所有指派」**留著**——其他五層都有同名功能，它是配套用的。已實際刪除這三支功能與其下游孤兒方法（domain service／repository 介面／實作），第四支未動 |
| **19** | 主系統有一處回傳的資料裡，兩個欄位對調了（專案成員和流程成員互換） | 既有錯誤，不是資安問題，但會讓讀這份資料的人看到錯的東西 |

---

::: {.callout .plain}
**下面只展開需要你自己判斷、或容易被誤解的幾條。** 其餘的修法明確，看上面表格的「怎麼修」那一欄就夠了——**沒有展開不代表沒查，也不代表不重要。**
:::

## 第 1 條：送一個空白查詢就撈光公司內的成員名冊

### 在哪裡、誰做什麼、發生什麼

**在哪裡**：查「這個專案有哪些成員」的那個功能。
**誰做什麼**：同一家公司裡任何一個能登入的人——**不必是這個專案的成員**，送出一個什麼條件都不填的查詢。
**發生什麼**：回來的是**公司內全部專案的成員名冊**。

負責這件事的入口只問一句「你登入了嗎」，**沒問「你是不是這個專案的人」**。而查詢條件裡的欄位全部不是必填，底層取資料的那段程式把「沒有給條件」理解成「不用過濾」——於是空白查詢等於整張表。

開卡的時候統籌者原本以為「至少要先知道一個專案編號」才讀得到。**實際比想的更嚴重：連專案編號都不必知道。**

### 打進去能拿到什麼

開發環境實測是**兩千多筆**（這個數每天都在變），每一筆包含：

| 欄位 | 為什麼有價值 |
|---|---|
| 專案編號 | 接著可以拿去打別的功能 |
| **誰是這個專案的管理者** | 🔴 **挑社交工程目標用的名單**——知道誰有權限批准什麼 |
| **成員的登入帳號** | 🔴 **拿去做針對性的密碼攻擊**，比亂猜帳號有效得多 |
| 成員暱稱 | 配合帳號，讓假冒信件更像真的 |

**跨客戶的部分已經被資料庫擋住**——那六張成員相關的資料表現在都開著客戶資料隔離，拿不到別家客戶的資料。**但同一家公司內部是完整名冊。**

### 建議怎麼修

| 步驟 | 做什麼 | 為什麼不能省 |
|---|---|---|
| **一** | 查詢與選單這兩支功能開頭，都補上「你是不是這個專案的成員」 | 只補一支，另一支還是拿得到同樣的資料 |
| **二** | 把專案編號改成必填，沒給就拒絕 | 不改必填，「空白查詢回整張表」這條路還在 |
| **三** | 同型的第 2、5、6 條一起修 | 四處是同一個缺陷、同一套修法，分開修會漏 |

**已確認所有呼叫這支功能的地方都帶專案或任務編號，改成必填不會影響現有功能。**

---

## 第 6 條：驗了人、沒驗物

### 在哪裡、誰做什麼、發生什麼

**在哪裡**：專案規劃頁的「指派任務」。

**誰做什麼**：小明**自己開一個新專案**，他就自動是那個專案的管理者。接著他送出指派請求時，**專案填自己的、任務填別人專案的**。

**發生什麼**：系統只查「小明是不是他自己那個專案的管理者」→ 是 → **放行**。**從來沒查「這個任務是不是他自己專案的」。**

這就是「驗了人、沒驗物」——身分檢查做了，但沒檢查他填進來的那樣東西是不是他有權碰的。第 10 條是同一個形狀（填進來的群組、控制項不驗歸屬）。

### 怎麼修

**寫入前先由任務、群組或控制項反查它真正屬於哪個專案，跟填進來的專案比對，不一致就拒絕。** 同一支檔案的「刪除」已經是這個寫法，照抄即可。

**已修的部分（FR-114.1-3）**：改成寫入前先確認**被指派的這個人是不是該專案的成員**，不是就拒絕。這一半擋掉了「把外人指派進自己專案」。回「找不到」而不是「無權限」是刻意的——回「無權限」等於告訴對方「這個帳號存在、只是不在這專案」，那會讓這支功能變成探查帳號的工具。開發環境既有 12,573 筆指派實測**全部**都是該專案成員，所以這道檢查不會擋到任何正常資料。

**另一半（FR-114.6-0a）**：寫入前再由任務反查它真正屬於哪個專案，跟填進來的專案比對，不一致或查不出來就拒絕。反查一律用系統唯一的歸屬判斷（先看控制項對應表上的稽核輪次，再看任務的主流程對到哪個稽核輪次）——**不可改查任務指派表**：拿要保護的表去驗證要寫進它的資料，擋不住第一筆。只有「新增指派」需要這道比對；修改與刪除都只能動已存在的那筆，專案由那筆紀錄反解，沒有「專案填 A、任務填 B」的入口。

### 修正時要守的規格：任務操作的角色規則

這套規則是決策者核對現況後定下來的。**「完成任務」那道檢查，弱點掃描那一塊有 8 支改狀態的功能也在吃，修的時候要一起改。**

| 動作 | 誰可以做 | 現況 |
|---|---|---|
| **完成／退回任務** | 被指派的人 ＋ 管理者 | 現在**專案任何參與者都能，連只能看的人都能完成別人的任務**（「批次完成」那支已經是正確寫法，單筆照抄即可） |
| **上傳／刪除佐證文件** | 被指派的人 ＋ 管理者 | 現在是任何參與者都能 |
| **問卷「填寫中」填答** | 填寫者本人 ＋ 管理者 | — |
| **問卷「審核中」填答與通過／退回** | 審核者本人 ＋ 管理者 | 現在**填寫者自己也能按通過結案**（畫面上有擋，系統內部沒擋） |
| **任務留言新增** | 專案參與者都可以 | 現況已符合 |
| **任務留言讀取** | 要補上「你是不是專案參與者」 | 現在只驗有沒有登入 |
| **管理者** | 上面每一項都可以做 | — |

---

## 第 7、8 條：兩組「現在打不到，但形狀很危險」的功能——裁定刪除

這兩組現在都造成不了實際傷害，但**它們代表的形狀值得單獨講**——因為擋住它們的不是設計，是巧合。

**判準是這一輪已經四次一致的原則：沒人用的東西不留，留著哪天接上就是沒檢查的入口。** 刪除前已確認全系統零使用。

### 第 7 條：漏接一條線，整支程式就靜默全開

這一塊裡有六支管成員的程式，寫法都是「**如果系統啟動時有把角色檢查的零件裝進來，才檢查；沒裝進來就直接執行**」。

**其中真的有一支沒裝。**

於是那支程式的新增、修改、刪除群組成員，全部不檢查權限。**系統不會報錯，也不會留下任何紀錄**——它就只是安靜地全部放行。

🔴 **後果比「沒檢查」更大的一件事**：這張群組成員表被系統拿來算「哪些專案我看得到」。**往裡面塞一筆，那個人就多看到一個專案。**

目前沒有對外入口打得到那三個寫入功能。**裁定**：三個寫入功能整段刪除；查詢那支留著，因為 AI 儀表板會呼叫它；資料表保留。

### 第 8 條：一組從沒啟用過的功能

流程參與者這組功能，三個面向指向同一件事：

- 負責檢查管理者身分的那段程式，如果查不到對應紀錄**就先提前結束**，真正的身分檢查排在提前結束的後面、**永遠執行不到**。程式旁邊的說明寫著「查不到的話交給後面的驗證邏輯拋出錯誤」，**但被點名的那個驗證方法根本不存在**，一旦走到就會直接出錯。
- 這組功能雖然已經接上，但**沒有任何地方在使用**。
- 它的資料表在開發環境是 **0 筆**，而且修改與刪除一定出錯——**等於這個功能完全不能用，而且從來沒有人回報過異常。**

**所以現在的實際結果是「程式壞掉」，不是「檢查通過放行」。**

**裁定**：新增、修改、刪除三個功能整段刪除。**資料表與回傳格式的定義要留著**——別的地方在用。

::: {.callout .crit}
**這兩組為什麼要當回事**

因為它們現在安全**不是因為有人在把關，是因為剛好沒人走到那條路**。

- 第 7 條：哪天有人幫那支程式加一個對外入口，就從「打不到」變成「完全開放」。
- 第 8 條：哪天有人很自然地把壞掉的地方修好，就從「程式出錯」變成「真正的權限繞過」。

**而修好它的人，會覺得自己在修 bug。** 他不會知道那個 bug 正是唯一的守門員。
:::

---

## 第 9 條：三次撞到同一件事

上表第 1 條（成員名冊）和第 5 條（任務指派），背後是**同一段程式**。

所有模組共用的那段取資料的底層有一條規則：**「查詢條件有填就加進去過濾，全部沒填就不過濾」**。

單看這條規則沒什麼問題——碼表、全站共用的下拉選單，回整張表本來就是對的。**問題在於「有主人的資料」也適用同一條規則。**

這條已經連續三次在不同模組放大成大量外洩：

| 第幾次 | 哪一塊 | 一個空白查詢回來多少 |
|---|---|---|
| 第一次 | 檔案上傳下載 | 全部客戶的檔案清單 |
| 第二次 | **這一塊**（成員名冊） | **公司內兩千多筆成員** |
| 第三次 | **這一塊**（任務指派） | **公司內一萬多筆指派紀錄** |

::: {.callout .decided}
**決策者裁定：底層不動，逐支補**

只修有洞的那 3 支（就是第 1、5 條的修法），**全站共用的底層不改**。

**理由**：底層改要把 17 支「刻意查全表」的功能逐一標記、跨全部模組，**功能不能壞的風險最大**，換來的只是防未來——**而現存的洞逐支補就全解了**。

🔴 **反悔條件：新功能第四次撞到同一件事，就改底層。**

兩個方案當初的取捨如下，留著供日後重新檢討時參考：

| 方案 | 優點 | 代價 |
|---|---|---|
| **在底層加一道「完全不帶條件就拒絕」** | 一次擋掉所有模組的同型問題，**往後新加的功能也自動受保護** | 要先盤點全站有哪些地方是刻意要查全表的（排程、管理員總覽、碼表），把它們改成明確標記——屬於跨全部模組的改動 |
| **維持底層不動，逐支功能補檢查**（已採納） | 改動範圍可控、每張工單獨立修 | 同型問題可能在下一支新功能再長出來 |

**盤點已經做完**（2026-09-15）：全部模組裡「查詢條件零必填」的有 17 支，其中**程式沒擋的只有 3 支**（資料庫層已經擋住跨客戶）——就是專案成員表、任務指派表，以及控制項層那批成員表。**判準是看這張表的資料有沒有「主人」**：有主人就該拒絕空白查詢，沒主人（碼表、公版資源）回整張表是對的。
:::

---

## 這塊的結論

::: {.callout .warn}
**一句話**：查到的 12 條裡有 1 條高風險——第 4 條在稽核輪次管理那塊查完後確認範圍更大、升為高（看得到別人專案的稽核判定與改善計畫，其中一支跨客戶也打得到）；其餘是「同一家公司內，不是這個專案的人看得到、動得了別人專案的東西」，**跨客戶的部分已經被資料庫擋住**。**更要緊的是這一塊還有約 86 個檔案沒碰過，其中任務與專案兩整塊功能完全沒查。**

**建議**：

1. **第 1、2、5、6 條是同一套修法，應該併成一批一起做**——四處是同一個缺陷，分開修一定會漏。
2. **第 7、8 條與第 18 條的刪除可以排在同一批**——它們是同一個判準（沒人用的東西不留），而且刪掉之後第 13 條也跟著消失。
3. **第 13、14 條要排在資安修正之前或同時**：第 13 條會讓驗收看到假的「通過」，第 14 條是那個「按下去顯示成功卻沒存」的畫面，已裁定整頁拆除。
4. **第 9 條的做法已經裁定**（逐支補、底層不動），修第 1、5 條時直接照做，不必再等決策。

**沒人用的地方，沒人會發現錯。** 這次新登記的兩件程式錯誤（第 16、19 條）都出在沒人走到的路徑上，正好印證了「三輪停手」的代價——**沒被使用、也沒被檢視的地方，錯了也不會有人回報。**

**關於沒查完的部分**：這不是待辦事項，是已經拍板的取捨。但**任何人問起「任務與成員管理查過了嗎」，正確的答案是「查了最關鍵的三輪，任務與專案兩整塊還沒查」**，不是「查過了」。
:::

| 統計 | |
|---|---|
| 檢視輪數 | **3 輪（原訂 7 輪）、109 個檔案** |
| 未檢視 | **約 86 個檔案**（模組本體 193 個，扣掉約 30 個零內容的橋接檔；任務與專案兩整塊完全沒查） |
| 通過的發現 | 14 條（三輪合計 42 票全投完），加上人工另外查出 7 條 |
| 登記的問題 | 12 條資安 ＋ 7 條程式錯誤 |
| 最嚴重 | 0 條（1 條高、8 條中、3 條低；第 4 條由中升高） |
| 已裁定刪除，已刪除 | **3 條**（第 7、8 條與第 18 條，全系統零使用，1.21.0 出貨） |
| 已裁定拆除整頁，已拆除 | **1 條**（第 14 條，兩個入口網址都拆了，1.21.0 出貨） |
| 已裁定退役，已退役 | **1 條**（第 10 條，1.21.0 出貨） |
| 已修 | **9 條**（第 1～6、11、12 條與第 9 條的逐支補法，1.21.0 出貨） |
| 主系統掃描另查出 | 3 條（第 20～22 條：中 2、低 1，全部已修，1.21.0 出貨） |

---

| 你想知道 | 看哪裡 |
|---|---|
| 我們用什麼方法查、結果有多可信 | [檢視方法與工具](GUIDE-01-method-and-tools.html) |
| 其他模組的檢視結果 | [回總報告首頁](index.html) |
