Guidant AI 資安檢視 · 跨模組專項

客戶資料隔離(跨模組專項檢查)

這不是一個模組,是橫跨所有模組的一次專項盤點——確認「A 客戶看不到 B 客戶的東西」這件事到底有沒有真的成立。答案當時是:不成立,而且有實測數字。1.21.0 出貨時五條裡三條已修、一條部分修(13 張表補好 12 張,剩下那張已改判為平台設定),另一條是走向多家客戶共用的 SaaS 版之前必做的那一塊。

先說明這一頁跟其他模組頁不一樣的地方

其他頁講的是「某一塊功能有什麼問題」。這一頁講的是一個橫跨整個產品的機制——它不屬於任何一塊,而是所有塊共用的那道牆。

所以這次檢視沒有用自動掃描工具:答案在資料庫的實際狀態裡,不在程式碼的寫法裡,工具幫不上忙。全部由人工逐張表查證,並在開發環境實際測過。

§1

這件事在產品裡是什麼

Guidant AI 有兩種賣法。落地版是一家客戶裝一套系統在自己的機房,整座資料庫就是那家客戶的。SaaS 版則是多家客戶共用同一套系統,A 公司的稽核資料與 B 公司的放在同一個資料庫裡,靠一道機制隔開——每個人查資料時,資料庫會自動幫他加上「只准看自己這家」這個條件,不必每支程式各自記得檢查。

產品現在走的是落地版,SaaS 版有規劃、短期不上線。但這道牆在落地版一樣要砌好,因為同一套程式碼兩種賣法共用,而且牆本身也順帶擋住「同一家客戶內不同單位」的越界。

產品說好的規則

往下看得到,平行看不到。

母公司看得到旗下子公司的資料;不同分支的客戶彼此完全隔開;法規框架、控制項目錄這類平台共用的東西全體可讀、只有原廠可寫。

這個規則 2026-06-29 就定案了。

為什麼這道牆特別重要

它是最後一道防線。

前面每一道檢查(這個人有沒有登入、有沒有權限、這筆是不是他的)只要有一支程式漏寫,這道牆就是唯一還擋得住的東西。

牆沒開,前面漏一次就直接外洩。


§2

檢視軌跡

檢視期間: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 個畫面一字不差;另外更正了交接文件摘要裡寫「三個畫面」的錯誤(實際是四個)。


§3

🔴 不是理論風險,當時有實測數字

檢視當時,用一把指向不存在客戶的鑰匙去查——照規則應該一筆都看不到:

查什麼 應該看到 檢視當時實際看到
待辦任務列表 0 筆 39 筆
專案 0 筆 213 筆
任務執行紀錄 0 筆 11,065 筆
工作流程執行紀錄 0 筆 11,016 筆

(數字是 2026-09-11 檢視當時的實測結果,由統籌者在開發環境用受隔離限制的帳號重跑確認過。)

當時客戶端還沒出事:要真的踩到,得先有人被指派成另一家客戶的角色,而那在測試環境與展示環境當時是 0 筆。但那個功能已經可以用了——所以是「還沒有人踩到」,不是「踩不到」。

為什麼拖到那時候才發現

這是修好一個洞之後才露出來的更大的洞。

以前沒有人「切換客戶」過——要切換得先被指派成另一家客戶的角色,而那個功能在另一張工單修好之前根本不能用。修好之後,才看見它後面的牆沒有砌。


§4

問題一覽

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

# 問題 風險 分類 出事會怎樣(誰受影響) 怎麼修 狀態
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 個接點;依決策者裁定排在程式面守門修完並測過一版之後)

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

§5

第 1 條的修補現況:13 張補上 12 張

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 出貨)。


§6

第 3 條:應用程式那一層的兩個缺口,都已補上

這條其實是兩個缺口:

缺口 現況
查詢任務詳細沒有任何守門——功能入口收了專案編號,程式裡從頭到尾沒有用到它 ✅ 已補上專案成員檢查
修改、刪除只驗「你在你填的專案裡是不是管理者」,沒核對「這筆任務屬不屬於那個專案」——拿自己是管理者的專案編號、配上別的專案的任務編號,檢查照樣會過 ✅ 讀、改、刪三支都先反查任務真正屬於哪個專案,與網址上的專案不符一律回「查無此資料」(不回「沒有權限」,避免洩漏那個任務編號存不存在)

任務歸屬讀的是輪次鏈(CM-2113),全系統共用同一個判斷;不能用指派表反查,否則還沒指派人的任務會被誤擋成「查無此資料」。兩張都隨 1.21.0 出貨(CM-2039 commit 8e33568d2、CM-2113 commit f52a53f1e)。

修法與任務與成員管理那塊的「驗了人、沒驗物」是同一種病。同一種病在稽核流程那塊還有六條未修(稽核流程第 17~22 條:跨專案列任務、匯入匯出換專案編號、強制開始等),歸 1.21.1 hotfix(母卡 CM-2289)。


§7

第 5 條:沒有牆的那一批表已經數清楚了

先說結論:落地版不受影響

落地版是一家客戶裝一套系統、整座資料庫就是那家客戶的——裡面本來就沒有別家客戶的資料,「A 客戶看到 B 客戶」這件事在落地版根本不成立。

這一條要等多家客戶共用同一套系統的 SaaS 版才成立,而 SaaS 版目前有規劃、短期不上線。所以這條的狀態不寫「未修」,寫「SaaS 版上線前必做」——它不是現在的洞,是產品走向 SaaS 之前的必要條件。

為什麼第 1 條那批盤點會整塊漏掉

第 1 條那批只挑「有客戶歸屬欄位」的表來查。而合規文件那一整塊(系統安全計畫、稽核計畫、稽核結果、稽核發現、矯正措施)本來就沒有客戶歸屬欄位——它們是靠「屬於哪個專案」間接連到客戶的,所以從第一步就不在清單上。

⚠️ 合規文件那一塊也是整份報告裡唯一一輪檢視都沒做過的區域。這次盤出來的清單,就是那一塊的第一個具體待辦。

現在數字長這樣

查什麼 實際查到
沒有牆的業務資料表 102 張
其中連客戶歸屬欄位都沒有的 101 張
用「指向不存在客戶」的鑰匙查專案 0 筆(牆擋住了)
同一把鑰匙查系統安全計畫 639 筆
同一把鑰匙查稽核發現 525 筆

102 張裡,要補的是 53 張

類別 張數 是什麼 要不要補
A 合規文件核心 45 系統安全計畫主檔+16 張子表(最大一張近四萬筆)、稽核計畫主檔+6 張子表、稽核結果 3 張、稽核發現/矯正措施/改善追蹤 8 張、合規資源庫 2 張、文件共用資料 3 張、零散 5 張 ✅ 要補
B 主專案零散 8 意見回饋 4 張(主檔有專案欄位)、任務子表 4 張(證據、留言、設備、部門)、輪次 2 張、流程控制項對照 1 張 ✅ 要補
C 平台共用 12 法規框架、目錄、控制項與段落(五萬多筆)、弱點檢測工具與規則、能力點、選單 ❌ 不用——全體客戶本來就該讀得到,只有原廠能寫
D 系統層 15 + 日誌分區 14 登入紀錄、登入憑證、密碼變更、版本紀錄、防竄改事件 ❌ 不用——這些資料沒有客戶主人

(公告與部門的對照表已另外裁定「靠主表擋」,不列在內。)

修法只有一種形狀,不是 53 套設計

53 張全部走同一種規則:「父表看得到,子表才看得到」——第 1 條那批就已經有幾張是這樣補的。不加欄位、不回填資料,子表一層一層跟著主檔走。

真正要設計的只有 4 個接點:

接點 怎麼連到客戶
系統安全計畫 靠一張對照表連到專案(那張對照表已經有牆)
稽核計畫 靠另一張對照表連到專案(已經有牆)
意見回饋 主檔本身就有專案欄位
🔴 合規資源庫 目前沒有任何連到客戶或專案的欄位,要先決定主人是誰。另有一張同名的資源庫表既有客戶欄位也有牆,兩張怎麼對應要先查清楚。這是 4 個接點裡唯一要動腦的

工作量:一支資料庫調整、一到兩天,外加驗證「開了牆會不會把正在用的資料藏起來」。這個驗證不能省——第 1 條修補時就踩過,流程範本那 59 筆得先回填歸屬才能開牆。

業界怎麼做(放在這裡給讀者對照)

多家客戶共用的系統,隔離不外乎三種做法:

做法 說明 我們的位置
一家客戶一套資料庫 隔離最徹底,但維運成本高 落地版就是這種
共用資料庫、每張表帶客戶欄位、由資料庫自動加條件 主流的 SaaS 做法 產品現在走這條,但只做了外圍
只在程式裡每支查詢自己擋 最不安全——漏一支就破 這輪查出的「只驗登入、不檢查歸屬」全是這種

子表沒有客戶欄位時,標準做法有兩種:子表也加一個欄位、從父表複製;或規則直接寫「父表看得到才看得到」。產品選的是後者,與第 1 條的修補方式一致。

決策者裁定:風險維持中,順序排在程式面之後

為什麼不提高風險等級:落地版一家客戶裝一套,這條不成立;只有 SaaS 版需要,而 SaaS 版短期不上線。

順序定成三步,不可對調:

  1. 先修程式面的守門缺口——那是現在就有、落地版也會中的。
  2. 測試一版。
  3. 再開這道牆。

理由:程式面先修、跑過一版之後,資料歸屬會被整理乾淨,到時候開牆踩到「在用的資料被藏起來」的坑會少很多。

歸屬:併進合規文件那一塊處理。總報告收尾的修正建議要把它列成明確的第二階段,排在程式面修正與測試之後——不要讓「晚一點」變成忘記。


§8

這塊的結論

一句話:這次專項最大的價值不是找到一個洞,是把「資料庫這道牆現在到底是什麼狀態」從猜測變成一張可以逐項驗證的清單——而且當場用一個任何人都能重跑的測試證明它沒生效。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. 先把應用程式那一層剩下的守門缺口修完——稽核流程那六條歸 1.21.1 hotfix,這是現在就有的風險。
  2. 測試一版,讓資料歸屬在這個過程裡被整理乾淨。
  3. 再把那 53 張的牆開起來,併進合規文件那一塊,作為 SaaS 版上線前的必要條件。
統計
檢視輪數 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 前另開

你想知道 看哪裡
我們用什麼方法查、結果有多可信 檢視方法與工具
其他模組的檢視結果 回總報告首頁