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