Guidant AI 資安檢視 · 跨模組專項
這不是一個模組,是橫跨所有模組的一次專項盤點——確認「A 客戶看不到 B 客戶的東西」這件事到底有沒有真的成立。答案當時是:不成立,而且有實測數字。1.21.0 出貨時五條裡三條已修、一條部分修(13 張表補好 12 張,剩下那張已改判為平台設定),另一條是走向多家客戶共用的 SaaS 版之前必做的那一塊。
先說明這一頁跟其他模組頁不一樣的地方
其他頁講的是「某一塊功能有什麼問題」。這一頁講的是一個橫跨整個產品的機制——它不屬於任何一塊,而是所有塊共用的那道牆。
所以這次檢視沒有用自動掃描工具:答案在資料庫的實際狀態裡,不在程式碼的寫法裡,工具幫不上忙。全部由人工逐張表查證,並在開發環境實際測過。
Guidant AI 有兩種賣法。落地版是一家客戶裝一套系統在自己的機房,整座資料庫就是那家客戶的。SaaS 版則是多家客戶共用同一套系統,A 公司的稽核資料與 B 公司的放在同一個資料庫裡,靠一道機制隔開——每個人查資料時,資料庫會自動幫他加上「只准看自己這家」這個條件,不必每支程式各自記得檢查。
產品現在走的是落地版,SaaS 版有規劃、短期不上線。但這道牆在落地版一樣要砌好,因為同一套程式碼兩種賣法共用,而且牆本身也順帶擋住「同一家客戶內不同單位」的越界。
往下看得到,平行看不到。
母公司看得到旗下子公司的資料;不同分支的客戶彼此完全隔開;法規框架、控制項目錄這類平台共用的東西全體可讀、只有原廠可寫。
這個規則 2026-06-29 就定案了。
它是最後一道防線。
前面每一道檢查(這個人有沒有登入、有沒有權限、這筆是不是他的)只要有一支程式漏寫,這道牆就是唯一還擋得住的東西。
牆沒開,前面漏一次就直接外洩。
檢視期間:2026-09-11(盤點)+ 2026-09-16、2026-09-20(兩次複查)+ 2026-09-21(缺口清單盤點)|範圍:13 張資料表 + 4 個資料查詢畫面 + 1 支功能入口,另加後續盤出的 102 張無牆資料表|共 1 輪(人工盤點,不用自動工具)
原始技術報告放在需求中心的 FR-087 站,檔名見下表最後一欄。那裡有每一張表的現況、應有狀態、修法分組與「開了會不會弄壞現有功能」的逐項查證。
| 輪次 | 查什麼 | 範圍 | 覆核投票 | 結果 | 原始報告檔名 |
|---|---|---|---|---|---|
| T1 | 每一張該隔開的資料表,牆到底有沒有開 | 13 表+4 畫面+1 入口 | 不適用(人工盤點,無自動工具、無投票) | 逐項用五個固定問題查完、全部答出、歸納成七組修法;另查證兩件事、更正交接文件裡一處推測 | scan-T1-isolation-gap-audit |
這一輪沒有三位獨立查核投票,要講明白為什麼
其他輪的可信度來自「三個獨立程序重查同一條、投票表決」。這一輪沒有那道手續。
替代的是更硬的證據:每一條結論都是直接問資料庫本身得到的答案(這張表的隔離開關是開是關、有幾條規則、有沒有客戶歸屬欄位),而且用一把指向不存在客戶的鑰匙實際查過——任何人都可以自己重跑一次驗證。
盤點結果與來源交接文件逐項比對,13 張表與 4 個畫面一字不差;另外更正了交接文件摘要裡寫「三個畫面」的錯誤(實際是四個)。
檢視當時,用一把指向不存在客戶的鑰匙去查——照規則應該一筆都看不到:
| 查什麼 | 應該看到 | 檢視當時實際看到 |
|---|---|---|
| 待辦任務列表 | 0 筆 | 39 筆 |
| 專案 | 0 筆 | 213 筆 |
| 任務執行紀錄 | 0 筆 | 11,065 筆 |
| 工作流程執行紀錄 | 0 筆 | 11,016 筆 |
(數字是 2026-09-11 檢視當時的實測結果,由統籌者在開發環境用受隔離限制的帳號重跑確認過。)
當時客戶端還沒出事:要真的踩到,得先有人被指派成另一家客戶的角色,而那在測試環境與展示環境當時是 0 筆。但那個功能已經可以用了——所以是「還沒有人踩到」,不是「踩不到」。
這是修好一個洞之後才露出來的更大的洞。
以前沒有人「切換客戶」過——要切換得先被指派成另一家客戶的角色,而那個功能在另一張工單修好之前根本不能用。修好之後,才看見它後面的牆沒有砌。
排序按風險。「出事會怎樣」那欄講的是業務影響——誰受影響、損失什麼,不是技術現象。
| # | 問題 | 風險 | 分類 | 出事會怎樣(誰受影響) | 怎麼修 | 狀態 |
|---|---|---|---|---|---|---|
| 1 | 13 張標有客戶歸屬的資料表,隔離沒有真正生效(3 張規則寫好了但開關沒開、1 張規則不完整、9 張連規則都沒有) | 🟠 高 | 客戶資料沒隔開 | 一家客戶的人看得到別家客戶的專案、待辦、任務執行紀錄與稽核資料。對一套稽核合規系統而言,這一條動搖的是產品最根本的承諾——客戶把自己的弱點、設備清單、稽核缺失交給我們保管,前提就是別家看不到 | 分五組處理:開開關的、先補規則再開的、要補查詢規則的、要先回填資料才能開的、建議重新分類不算缺口的 | ⚠️ 部分修——12 張已補上隔離,剩「日誌轉送設定」那張仍關閉,已改判為平台層設定、寫入只給平台管理員(見下方進度) |
| 2 | 4 個資料查詢畫面整個繞過隔離機制(使用者登入後的「我的任務」清單、判斷「這個人能做哪些操作」的權限總覽,以及兩份選單清單) | 🟠 高 | 客戶資料沒隔開 | 任何一個登入的人,打開「我的任務」頁面就會撞到——上面那個「應該 0 筆、看到 39 筆」的待辦列表就是其中之一。這四個畫面是用建立者的身分去查底層資料的,而建立者是系統最高權限帳號,等於牆對它們完全不存在。稽核儀表板上的待辦數量卡片讀的也是同一個畫面 | 「我的任務」清單與權限總覽兩支補上「用查詢者自己的身分執行」這個設定;兩份選單清單查遍程式找不到任何地方在用,直接移除 | ✅ 已修(2026-09-16 複查確認;本報告撰寫時再次查證仍成立) |
| 3 | 查詢任務詳細資料的功能,收了專案編號卻從頭到尾沒用它 | 🟡 中 | 只驗登入、不檢查歸屬 | 任何登入的人在任務列表上看到一筆別人專案的任務編號,就點得開它的完整內容。入口雖然要填專案編號,但不管填真的、全零、還是亂打一串字,三種都查得到同一筆資料——「這筆任務屬不屬於你說的那個專案」從來沒被檢查過 | 與檔案下載那一組(同樣的病、不同位置)合併成同一張工單處理。任務歸屬改讀輪次鏈(FR-114 CM-2113),修正未指派任務被誤擋 | ✅ 已修(CM-2039,commit 8e33568d2;CM-2113 f52a53f1e) |
| 4 | 兩支半夜自動執行的清理程式,靠「找不到身分時給最高權限」這條規則才跑得動 | 🟡 中 | 要先做產品決策 | 這不是漏洞,是規劃上的相依:未來收緊那條規則的那一天,這兩支清理程式會安靜地停止運作、而且不會報錯,殘留資料會一直堆積卻沒人發現 | 收緊那條規則時,同時給這兩支程式一個明確的系統身分 | ✅ 已修(2026-09-16 複查確認:兩支都改成用具名的系統身分執行,原本那段說明文字也改寫成反向警語) |
| 5 | 有一整類業務資料表連客戶歸屬欄位都沒有,牆沒有東西可以依據——已盤清:共 102 張沒有牆,其中 101 張連欄位都沒有 | 🟡 中 | 客戶資料沒隔開 | 落地版不受影響——一家客戶裝一套、整座資料庫就是那家客戶的,「看到別家」這件事不成立。但走向多家客戶共用的 SaaS 版時,合規文件那一整塊就沒有最後一道防線:實測用一把指向不存在客戶的鑰匙去查,專案看到 0 筆(牆擋住了),系統安全計畫看到 639 筆、稽核發現看到 525 筆 | 補上「父表看得到、子表才看得到」的跟隨規則,不加欄位、不回填資料。53 張要補、49 張確認不用補,真正要設計的只有 4 個接點(見下方清單) | SaaS 版上線前必做(清單已盤好:53 張、4 個接點;依決策者裁定排在程式面守門修完並測過一版之後) |
下面只展開需要你自己判斷、或容易被誤解的幾條。 其餘的修法明確,看上面表格的「怎麼修」那一欄就夠了——沒有展開不代表沒查,也不代表不重要。
2026-09-14 一批資料庫調整把缺口補起來,隨 1.21.0 出貨。2026-09-20 連開發環境唯讀重查,結果如下:
| 修法分組 | 哪些表 | 現況(唯讀實查) |
|---|---|---|
| 只需要打開開關 | 專案、客戶雲端硬碟連動設定 | ✅ 隔離已開、各 4 條規則 |
| 要先補規則再開 | 任務執行、資訊系統、矯正措施、證據分類執行紀錄、證據分類標準答案、框架解析工作、使用者角色、使用者客戶對照(8 張) | ✅ 全部已開、各 4 條規則 |
| 要補查詢規則 | 工作流程執行紀錄 | ✅ 已開、4 條規則齊 |
| 要先回填資料才能開 | 流程範本 | ✅ 已開;59 筆全部標成「平台共用」、無一筆歸屬空白 |
| 建議重新分類,不算缺口 | 日誌轉送設定 | ⚠️ 仍是關閉、0 條規則——這正是報告自己標「本質是平台層設定、已有權限把關,建議不當隔離缺口」的那一張;它的寫入權限已收到只給平台管理員(日誌第 1 條,已修) |
而且這批新補的規則沒有踩到另一個已知的坑:弱點檢測那塊查出出貨基線裡有 11 張表的隔離規則方向寫反了(子單位看得到母單位、母單位反而看不到子單位)。這 13 張新補的規則逐條查過,方向全部是對的,不會再加進那 11 條的待修清單。
再用當時那把「指向不存在客戶」的鑰匙重測一次(2026-09-20 實跑):
| 查什麼 | 檢視當時 | 現在 |
|---|---|---|
| 專案 | 213 筆 | 0 筆 |
| 待辦任務列表(那個繞過隔離的畫面) | 39 筆 | 0 筆 |
| 任務執行紀錄 | 11,065 筆 | 0 筆 |
| 工作流程執行紀錄 | 11,016 筆 | 0 筆 |
這四個數字歸零,是這次專項最直接的成果。
「牆補好了」不等於「門也關好了」——兩層要分開驗
資料庫這道牆擋的是「別家客戶」;應用程式那一層擋的是「同一家客戶裡不該看的人」,兩者不能互相取代。
具體例子:存放檔案的那張表資料庫這道牆補上了(已加客戶歸屬欄位、隔離已開、四條規則齊全,唯讀實查時以受隔離的帳號查只看得到本客戶的 14 筆測試檔案)——但這只擋住跨客戶。同一家客戶內、不同專案之間,要靠「下載檔案」「換發下載通行證」「刪除檔案」那三支功能自己檢查「這個檔案是不是你的」——這一層由檔案上傳下載第 1~3、7 條補上(CM-2033,commit a334f5385,1.21.0 出貨)。
這條其實是兩個缺口:
| 缺口 | 現況 |
|---|---|
| 查詢任務詳細沒有任何守門——功能入口收了專案編號,程式裡從頭到尾沒有用到它 | ✅ 已補上專案成員檢查 |
| 修改、刪除只驗「你在你填的專案裡是不是管理者」,沒核對「這筆任務屬不屬於那個專案」——拿自己是管理者的專案編號、配上別的專案的任務編號,檢查照樣會過 | ✅ 讀、改、刪三支都先反查任務真正屬於哪個專案,與網址上的專案不符一律回「查無此資料」(不回「沒有權限」,避免洩漏那個任務編號存不存在) |
任務歸屬讀的是輪次鏈(CM-2113),全系統共用同一個判斷;不能用指派表反查,否則還沒指派人的任務會被誤擋成「查無此資料」。兩張都隨 1.21.0 出貨(CM-2039 commit 8e33568d2、CM-2113 commit f52a53f1e)。
修法與任務與成員管理那塊的「驗了人、沒驗物」是同一種病。同一種病在稽核流程那塊還有六條未修(稽核流程第 17~22 條:跨專案列任務、匯入匯出換專案編號、強制開始等),歸 1.21.1 hotfix(母卡 CM-2289)。
落地版是一家客戶裝一套系統、整座資料庫就是那家客戶的——裡面本來就沒有別家客戶的資料,「A 客戶看到 B 客戶」這件事在落地版根本不成立。
這一條要等多家客戶共用同一套系統的 SaaS 版才成立,而 SaaS 版目前有規劃、短期不上線。所以這條的狀態不寫「未修」,寫「SaaS 版上線前必做」——它不是現在的洞,是產品走向 SaaS 之前的必要條件。
第 1 條那批只挑「有客戶歸屬欄位」的表來查。而合規文件那一整塊(系統安全計畫、稽核計畫、稽核結果、稽核發現、矯正措施)本來就沒有客戶歸屬欄位——它們是靠「屬於哪個專案」間接連到客戶的,所以從第一步就不在清單上。
⚠️ 合規文件那一塊也是整份報告裡唯一一輪檢視都沒做過的區域。這次盤出來的清單,就是那一塊的第一個具體待辦。
| 查什麼 | 實際查到 |
|---|---|
| 沒有牆的業務資料表 | 102 張 |
| 其中連客戶歸屬欄位都沒有的 | 101 張 |
| 用「指向不存在客戶」的鑰匙查專案 | 0 筆(牆擋住了) |
| 同一把鑰匙查系統安全計畫 | 639 筆 |
| 同一把鑰匙查稽核發現 | 525 筆 |
| 類別 | 張數 | 是什麼 | 要不要補 |
|---|---|---|---|
| A 合規文件核心 | 45 | 系統安全計畫主檔+16 張子表(最大一張近四萬筆)、稽核計畫主檔+6 張子表、稽核結果 3 張、稽核發現/矯正措施/改善追蹤 8 張、合規資源庫 2 張、文件共用資料 3 張、零散 5 張 | ✅ 要補 |
| B 主專案零散 | 8 | 意見回饋 4 張(主檔有專案欄位)、任務子表 4 張(證據、留言、設備、部門)、輪次 2 張、流程控制項對照 1 張 | ✅ 要補 |
| C 平台共用 | 12 | 法規框架、目錄、控制項與段落(五萬多筆)、弱點檢測工具與規則、能力點、選單 | ❌ 不用——全體客戶本來就該讀得到,只有原廠能寫 |
| D 系統層 | 15 + 日誌分區 14 | 登入紀錄、登入憑證、密碼變更、版本紀錄、防竄改事件 | ❌ 不用——這些資料沒有客戶主人 |
(公告與部門的對照表已另外裁定「靠主表擋」,不列在內。)
53 張全部走同一種規則:「父表看得到,子表才看得到」——第 1 條那批就已經有幾張是這樣補的。不加欄位、不回填資料,子表一層一層跟著主檔走。
真正要設計的只有 4 個接點:
| 接點 | 怎麼連到客戶 |
|---|---|
| 系統安全計畫 | 靠一張對照表連到專案(那張對照表已經有牆) |
| 稽核計畫 | 靠另一張對照表連到專案(已經有牆) |
| 意見回饋 | 主檔本身就有專案欄位 |
| 🔴 合規資源庫 | 目前沒有任何連到客戶或專案的欄位,要先決定主人是誰。另有一張同名的資源庫表既有客戶欄位也有牆,兩張怎麼對應要先查清楚。這是 4 個接點裡唯一要動腦的 |
工作量:一支資料庫調整、一到兩天,外加驗證「開了牆會不會把正在用的資料藏起來」。這個驗證不能省——第 1 條修補時就踩過,流程範本那 59 筆得先回填歸屬才能開牆。
多家客戶共用的系統,隔離不外乎三種做法:
| 做法 | 說明 | 我們的位置 |
|---|---|---|
| 一家客戶一套資料庫 | 隔離最徹底,但維運成本高 | 落地版就是這種 |
| 共用資料庫、每張表帶客戶欄位、由資料庫自動加條件 | 主流的 SaaS 做法 | 產品現在走這條,但只做了外圍 |
| 只在程式裡每支查詢自己擋 | 最不安全——漏一支就破 | 這輪查出的「只驗登入、不檢查歸屬」全是這種 |
子表沒有客戶欄位時,標準做法有兩種:子表也加一個欄位、從父表複製;或規則直接寫「父表看得到才看得到」。產品選的是後者,與第 1 條的修補方式一致。
決策者裁定:風險維持中,順序排在程式面之後
為什麼不提高風險等級:落地版一家客戶裝一套,這條不成立;只有 SaaS 版需要,而 SaaS 版短期不上線。
順序定成三步,不可對調:
理由:程式面先修、跑過一版之後,資料歸屬會被整理乾淨,到時候開牆踩到「在用的資料被藏起來」的坑會少很多。
歸屬:併進合規文件那一塊處理。總報告收尾的修正建議要把它列成明確的第二階段,排在程式面修正與測試之後——不要讓「晚一點」變成忘記。
一句話:這次專項最大的價值不是找到一個洞,是把「資料庫這道牆現在到底是什麼狀態」從猜測變成一張可以逐項驗證的清單——而且當場用一個任何人都能重跑的測試證明它沒生效。13 張表已補上 12 張,實測數字從 39/213/11,065/11,016 全部歸零;五條裡三條已修、一條部分修,隨 1.21.0 出貨。
這次專項也留下兩件事,必須一起看:
一、牆與門要分開看。 牆擋的是「別家客戶」,門(應用程式那一層「這筆資料是不是你的」的檢查)擋的是「同一家客戶裡不該看的人」——兩者不能互相取代。 門這一層是整份報告最大的一組問題,大部分已隨 1.21.0 修好(檔案下載、任務讀改刪、問卷、稽核證明等);還沒修的是稽核流程那塊的六條任務越權(稽核流程第 17~22 條),歸 1.21.1 hotfix(母卡 CM-2289)。這是落地版也會中的問題。
二、走向 SaaS 版之前還差一塊,而且已經數清楚了。 沒有牆的業務資料表共 102 張,其中要補的是核心合規文件 45 張+零散 8 張,合計 53 張,修法只有「父表看得到、子表才看得到」一種形狀,真正要設計的只有 4 個接點、一到兩天的工作量。落地版不受這一塊影響——一家客戶裝一套,整座資料庫就是那家客戶的。
建議照這個順序做:
| 統計 | |
|---|---|
| 檢視輪數 | 1 輪(人工盤點)+ 2 次複查 + 1 次缺口清單盤點 |
| 盤點範圍 | 13 張資料表 + 4 個資料查詢畫面 + 1 支功能入口,另加 102 張無牆資料表 |
| 歸納出的修法分組 | 7 組 |
| 最嚴重 | 0 條 |
| 高風險 | 2 條(1 條部分修、1 條已修) |
| 已修 | 3 條(第 2、3、4 條,1.21.0 出貨) |
| 部分修 | 1 條(第 1 條:13 張補上 12 張,剩下那張已改判為平台設定) |
| 列為 SaaS 版上線前必做 | 1 條(第 5 條,落地版不成立;待補清單 53 張、4 個接點已盤好) |
| 未修 | 0 條(五條全部有著落:三條已修、一條部分修、一條排入 SaaS 版上線前) |
| 修正工單 | CM-2039、CM-2113(第 3 條);第 1、2、4 條隨資料庫調整修好;第 5 條 SaaS 前另開 |