檢查日期 2026-09-19|對應卡片 CM-1950|檢查範圍 16 個檔案 1,850 行
這一棒範圍內沒有找到任何資安漏洞——工具提的唯一一條被三位檢查員一致駁回,我自己把卡片列的七個重點逐項開檔核對後也同意:守門、租戶隔離、插件接線這三道該擋的都擋住了。
白話講這棒在查什麼:「AI 分類設定」就是客戶用來告訴 AI「你是誰、怎麼判、什麼算證據」的那一份設定,它管的是整個框架版本底下所有專案的 AI 行為。所以要問三件事——誰能改它(不能是任何人)、看得到多少(別的客戶的人設與提示詞是客戶的稽核方法論,不能外流)、套件掛進系統時零件缺了會怎樣(該拒絕啟動,不能靜默放行)。三件都查了,都沒問題。
唯一值得決策者知道的一件事,但它不是漏洞:查「這個租戶有哪幾家 AI 可以選」的那支端點,確實沒有像它隔壁四支一樣要求管理員身分——任何登入者都打得到。三位檢查員一致判定這不算漏洞,理由是它回的只有「anthropic」「openai」這種廠商名字加上一張寫死在程式裡的公開型號表,沒有金鑰、沒有網址、也拿不到別的客戶的資料;而且前端的分類操作畫面本來就會呼叫它來填下拉選單,那些畫面的使用者是專案成員而不是管理員,真的加上管理員檢查會把正常功能擋掉。我開檔核對過這三點都屬實,同意這個判定。詳見下方「逐項查證②」。
證據自動分類要用 AI,而「用哪一家的 AI、哪個型號、要它想多深、要它扮演什麼角色、怎麼判斷算不算證據」這些,客戶可以自己設定。這一棒看的就是這份設定的管理後台那一半,加上整個套件怎麼掛進系統的那層骨架。
十六個檔案分成三組:
選它當第四棒的理由:設定管所有專案的 AI 行為,一旦被任意登入者改掉,等於可以左右整個系統的合規判定結果;而插件骨架是所有端點認證的唯一來源,那層漏一個洞就是一整排端點變成公開的。
掃描目標 ~/Projects/Jedicogy/module/jedi-python-package/jedi-evidence-classification,branch feature/review,版本 955e409,mode scan,effort low,focus attack-surface。
範圍十六個檔案:
| 檔案 | 行數 | 角色 |
|---|---|---|
app/service/classification_profile_service.py |
311 | 設定的建改刪查主邏輯、守門、四層解析鏈 |
migrations/005-classification-profiles.sql |
175 | 設定表的建表腳本(含權限與租戶隔離規則) |
api/routing.py |
190 | 全部 25 支端點的網址對照表,登入檢查在這裡套上 |
domain/ports.py |
283 | 套件對主系統要求的「零件規格書」(介面定義) |
plugin/contract.py |
144 | 插件對外的契約型別與必填零件清單 |
plugin/__init__.py |
125 | 插件註冊入口 |
plugin/assembly.py |
114 | 接線檢查、登入檢查的套法、blueprint 組裝 |
domain/llm_models.py |
95 | AI 型號碼表(純資料) |
api/routes/classification_profile_route.py |
85 | 五支設定端點的進出口 |
api/schemas/classification_profile_schema.py |
84 | 進出欄位定義 |
infra/repository/classification_profile_repository_impl.py |
59 | 資料庫查詢實作 |
domain/service/classification_profile_domain_service.py |
57 | 領域層薄封裝 |
plugin/runtime.py |
54 | 執行期組件取用 |
api/guards.py |
33 | 執行期組件的取用入口(實際上沒有守門邏輯,檔名容易誤會) |
domain/entity/classification_profile_query_entity.py |
21 | 查詢條件的資料結構 |
plugin/migrations.py |
20 | 建表腳本的程式化出口 |
這支套件的這一塊從來沒有被掃過。 設定功能是 FR-107 T-5.x/CM-1864(建表與四層解析)、CM-1867(守門從平台管理員放寬到租戶管理員)、CM-1885(型號碼表換代與思考深度三檔)、CM-1888(型號反查廠商)連續做出來的,全部都在 955e409 這個版本裡。
十六個檔案全部讀完,就是範圍給的全部。
不在本棒範圍、但這份報告的結論依賴它們(我開檔查證時讀了,屬於對照不屬於審查):
core/plugins/evidence_classification.py(守門怎麼實作、金鑰怎麼取)app/system_config/service/ai_provider_key_resolver.py(金鑰解析鏈本體,199 行)evidence_batch_service.py(設定怎麼被分類流程消費)AutoClassifyBatch.vue/ClassificationProfilePanel.vue(誰在呼叫那支端點)金鑰解析鏈的本體不在本棒——本棒只答得了「套件這一半有沒有把金鑰或『誰有金鑰』露出去」,答不了「解析鏈本身守不守得住」。那是主系統接線那一棒的事,FR README 已註明兩支要同一棒做。
低強度跑法不做元件盤點、不做威脅建模、不跑額外廣度掃描,completenessCheckOutcome 是 not-applicable(指定範圍的掃描本就不適用)。派兩位研究員、兩位都回報;兩個候選去重成一個,該候選 0:3 被駁回,沒有候選遺失、沒有候選未被審、沒有被上限砍掉。
工具沒有執行任何程式碼:沒有打過任何端點、沒有跑測試、沒有連過資料庫。下面所有判斷都是讀原始碼推出來的。
工具的偏食:兩位研究員都只盯「守門有沒有漏」這一類,而且兩位提的是同一條。卡片列的七個重點裡,工具只碰到①②的一小角,③④⑤⑥⑦完全沒報,全部由我逐項開檔補查(見下方「卡片重點逐項查證」,每項都標明是工具報的還是人工查的)。
範圍內淨新增零條。 沒有發現需要開修正卡的資安問題。
工具提出、檢查員駁回的那一條記錄如下(不計入發現數):
| 候選 | 工具評的嚴重度 | 檢查員判定 | 為什麼駁回 |
|---|---|---|---|
| 查可用型號的端點沒有管理員檢查 | 低 | 3 票全數駁回 | 回的是廠商名字加一張公開型號表,沒有金鑰也沒有別人的資料;而且前端的分類操作畫面本來就要呼叫它,加了檢查會擋掉正常功能 |
我另外記下兩件不是資安問題、但下一任接手的人應該知道的事(都不開卡):
| # | 是什麼 | 為什麼不是資安問題 | 記在哪 |
|---|---|---|---|
| A | 設定表的「AI 人設」與「判斷指引」兩個欄位沒有長度上限,而它們會被寫進給 AI 的指令檔 | 寫得進去的只有租戶管理員(自己人),寫進去的內容只影響自己租戶自己的分類結果;這是「管理員可以把自己的 AI 設定寫得很爛」不是「外人可以動手腳」 | 下方逐項查證③ |
| B | 設定裡的「預設廠商/預設型號」兩個欄位存得進去、畫面填得出來,但分類真的跑起來時沒有人去讀它們(只有「預設思考深度」被讀) | 是功能沒接完,不是資安缺口——使用者設了沒作用,症狀是「我明明設了 OpenAI 怎麼還是跑 Anthropic」 | 下方逐項查證⑦ |
無。
卡片列了七個重點。工具不照清單走,所以每一項我都回頭核了一次,下面標明哪些是工具碰過的、哪些是我人工開檔查的。
問的是:設定的建改刪查這五支,到底誰打得到?
查到的:classification_profile_service.py 的四支寫入與讀取方法——列清單(:154)、新增(:168)、修改(:199)、刪除(:216)——每一支的第一行都是 self._require_settings_manager(),四支無漏。
_require_settings_manager(:221-228)問的是主系統提供的守門零件 can_manage_settings(),回 false 就拋 403。主系統那一半(core/plugins/evidence_classification.py:123-147)判的是租戶管理員,用的是「儲存設定」那顆既有的能力點(storage-config.update),而且它委派給 common.authz(FR-048 統一守門),沒有自己另抄一份查詢。
🔴 這裡有一個做對了、值得記下來的地方:守門零件沒接上時,程式是當場拋錯拒絕服務(_guard() :230-241),不是「沒接就放行」。這一點在 E3 的舊 Drive 線正好是反例——那條線的查詢端點只驗登入。這裡做對了。
「租戶管理員改不到原廠設定」也確認成立:_require_own_profile(:243-253)比對這筆設定的租戶編號與呼叫者的租戶編號,不一樣就拋 403(而不是假裝不存在)。原廠那一列的租戶編號是 1,一般客戶的不是,所以改不動。
結論:這一項沒問題。
問的是:查「這個租戶有哪幾家 AI 可以選」的那支端點(available_models,:119-138),回的東西裡有沒有洩漏什麼。
工具說:這支確實沒有 _require_settings_manager(),跟隔壁四支不一樣,所以任何登入者都打得到。
三位檢查員一致駁回,我開檔核對三個駁回理由,全部屬實:
回的內容裡沒有金鑰也沒有網址。 我追到主系統的 ai_provider_key_resolver.py:184-199:configured_providers() 這支迴圈跑過每一家,只做一件事——解得出金鑰就把廠商的名字(字串,例如 "anthropic")加進清單。金鑰本身、網址、任何設定值都沒有進到回傳值裡。套件這一邊(:129-137)拿這串名字去跟寫死在程式裡的型號表(llm_models.py:49-54,公開資訊)取交集,回出去的是 provider/model_id/display_name/supports_vision/default 五個欄位——沒有 base_url、沒有 is_set 以外的任何設定狀態。卡片擔心的「回應裡會不會夾帶 base_url」,答案是不會。
拿不到別的租戶的東西。 租戶編號來自呼叫者自己的登入脈絡(:125 呼叫 _require_identity(),:303-311 從 get_user_context() 取),不是從網址或請求內容來的,所以沒有「改個數字看別人的」這種玩法。
前端的正常功能依賴它。 我在前端 grep 過,呼叫這支的有四個地方:ClassificationProfilePanel.vue:43(設定畫面,管理員用)、AutoClassifyBatch.vue:315、AutoClassifyList.vue:265、autoClassifyShared.js:79。後面三個是分類操作畫面,使用者是專案成員不是租戶管理員——加上管理員檢查會讓他們的型號下拉選單變空白或直接 403。
所以洩漏的極限是:一個已經登入的自家人,知道「我們公司有設 OpenAI 的鑰匙」這件事。 不是金鑰、不是別人的資料、不是跨租戶。我同意檢查員的判定,不開卡。
另外確認一件卡片特別點名的事:四層解析鏈落到原廠那一層時,分類確實會用原廠的鑰匙跑(resolve :84-101 會回原廠那筆設定)。這是 CM-1867 裁示 D13 的刻意設計——「鎖原廠」鎖的是「不准改」,不是「不准用」。記在這裡是為了讓下一個看到這段程式的人不要誤判成漏洞。
問的是:新增/修改設定時,送進來的內容有沒有被檢查?
查到的(_validated :265-301):
| 欄位 | 有沒有檢查 | 檢查什麼 |
|---|---|---|
framework_version_id |
✅ | 強制轉成整數,轉不了就拋錯 |
enable |
✅ | 強制轉成布林 |
evidence_hints |
✅ | 必須是字典,不是就拋 EC_PROFILE_HINTS_INVALID |
confidence_threshold_default |
✅ | 必須是數字且落在 0.0~1.0 之間 |
name/persona |
⚠️ 只檢查「新增時不可空白」 | 沒有長度上限 |
guidance |
❌ 無檢查 | 沒有長度上限 |
provider_default/model_default |
❌ 無檢查 | 沒有比對型號碼表 |
effort_default |
❌ 在這裡無檢查 | 但下游有(見下) |
白名單本身是做對的:_validated 只把列在清單裡的欄位挑出來,沒列的一律丟掉——所以送額外欄位(例如想偷偷改 tenant_id)是沒用的。
兩個沒檢查的地方,我判斷都不構成資安問題:
長度沒上限(記為觀察 A):persona/guidance 會被寫進給 AI 的指令檔(evidence_batch_service.py:1376-1393 → prompt.json,:1108)。但寫得進去的只有租戶管理員,而且影響範圍只有他自己租戶的分類結果。這是「管理員可以把自己的設定寫壞」,不是「外人可以動手腳」。資料庫那兩欄是 TEXT 型別(005:36-37),沒有硬上限。真要說風險,是有人貼一份超大文字進去讓自己的分類變慢或變貴——那是自傷。不開卡。
廠商/型號沒比對碼表:這兩欄存進去的是什麼字串都收。但真正要跑分類的時候有第二道:_resolve_run_params(evidence_batch_service.py:1317-1320)會用 spec_for() 去碼表查,查不到就拋 EC_INVALID_MODEL、整批擋下。所以存得進髒字串,但跑不起來——症狀是功能錯誤不是資安問題。思考深度那欄同理,_resolve_effort(:1330-1343)每一層都先驗合不合法,不合法就往下一層退。
卡片特別問的 apply=False:我 grep 過整個套件,0 命中,確認沒有這個模式。
還有一件事值得記:classification_profile_schema.py 裡定義了一個 ClassificationProfileWriteRequestSchema(:11-29,還帶了 effort_default 的 OneOf 檢查),但我 grep 全套件,這個 class 除了自己那行定義之外沒有任何地方引用它。也就是說它是死的,真正在把關的是 service 層的 _validated。這不是漏洞(_validated 有在做事),但下一個人看到這支 schema 可能會以為進來的東西被 marshmallow 驗過了——實際上沒有。
問的是:建表腳本裡的租戶隔離規則(RLS,就是「每個客戶只能看自己資料」的資料庫層機制)形狀對不對?原廠那一列被放行到什麼程度?
查到的(005-classification-profiles.sql:105-156),四條規則:
| 動作 | 規則內容 | 原廠那列(租戶 1)有沒有放行 |
|---|---|---|
讀 (:132-135) |
超級管理員 or 自己租戶 or tenant_id = 1 |
✅ 有放行 |
新增 (:139-141) |
超級管理員 or 自己租戶 | ❌ 沒放行 |
修改 (:145-147) |
超級管理員 or 自己租戶 | ❌ 沒放行 |
刪除 (:151-153) |
超級管理員 or 自己租戶 | ❌ 沒放行 |
這正是卡片問的「寫入三條有沒有跟著放行(不該)」——答案是沒有跟著放行,形狀正確。 讀的時候放行原廠那列是必要的(四層解析鏈的第二層與第四層要讀得到原廠設定,擋掉的話所有租戶都只會拿到程式內建的最陽春版本);寫入三條不放行,所以業務租戶改不動原廠設定。資料庫這一層與程式那一層(_require_own_profile)是兩道獨立的鎖,都鎖住了。
原廠那一列的內容會被所有租戶讀到——包含它的人設全文。我開檔看了那一列的實際內容(005:166-171 的 seed):是一段通用的英文「你是合規評估專家,把證據對到評估項目」,刻意不含任何框架名(註解寫明理由:寫上 CMMC 的話 ISO 客戶的 AI 會一開口就談錯標準)。沒有客戶資料,沒有敏感內容。 卡片擔心的「客戶的稽核方法論外流」不成立——外流的是原廠自己寫的通用範本。
查詢那一側也核過(classification_profile_repository_impl.py:47-58):list_for_tenants 拿到的租戶清單是 service 層算的(:156),內容是 [自己] 或 [自己, 1]——不會出現第三個租戶編號。而且前面有 if not tenant_ids: return [],空清單直接回空而不是回全表(這正是 E5 那一棒要查的「空條件回全表」陷阱,這一支沒有踩到)。
find_generic(:30-45)用的是 .is_(None) 而不是 == None——註解寫明了理由(SQL 的 = NULL 恆為 unknown,會永遠查無而且不報錯)。這是對的寫法。
這一項是本棒最重要的查證,因為插件殼是所有端點認證的唯一來源。
問的是:主系統掛這個套件時如果漏接某個零件,會發生什麼?
查到的,分成三類:
第一類——缺了就拒絕掛載(plugin/assembly.py:19-33)。 必填清單是四個(contract.py:29):登入檢查、專案目錄、專案角色守門、證據來源。缺任何一個,_assert_wiring 直接拋 RuntimeError,服務起不來。註解寫明了為什麼不能改成「有就用、沒有就跳過」:跳過的話觸發分類/改結果/歸檔這些端點會全部變成公開端點,而服務照常起得來、健康檢查照樣綠燈。這是做對的。
第二類——缺了會拋錯但不擋啟動。 管設定的那個守門零件(platform_admin_guard)不在必填清單裡。我核過缺了會怎樣:_guard()(:230-241)在被呼叫時拋 RuntimeError,訊息明講「拒絕以無守門狀態服務」。所以設定的五支端點會 500,不是放行——這是安全的失敗方式。決策上把它放在選填是合理的:不需要設定功能的 consumer 可以不接,接了才會用到。
第三類——缺了會降級成空回應。 ai_provider_config 缺了的話 available_models 回空清單(:127-128),前端顯示「尚未設定任何供應商金鑰」。這是刻意的(註解寫明「比列出一堆選了會 401 的模型好」),也不涉及安全。
登入檢查怎麼套上去的(_guarded :36-46):用動態產生子類別的方式,把 get/post/put/delete/patch 五個動詞各自包一層。註解特別說明不直接改原本類別的屬性——因為那會污染跨 app 的共用類別(同一套件掛到兩個 app 時互相影響)。這個作法是對的。
🔴 卡片要我逐支核對「每一支 add_resource 是不是都經過 R() 包過」——我用程式解析了 routing.py 的每一個 add_resource 呼叫:總共 25 支,25 支全部第一個參數都是 R(...),零遺漏。 這是本棒最該核的一件事,因為漏包一支就是那支端點變成不需要登入,而路由表看起來完全正常。
金鑰進套件的入口(container_env,contract.py:63):我 grep 了整個套件裡所有碰到它的地方(7 處),沒有任何一處把它 log 出來。它只被拿去傳給容器執行器(assembly.py:100 → classifier_container_runner.py:150 合併成容器環境變數)。金鑰沒有在本棒範圍內被記錄下來。(容器執行那一段是 E1 的範圍,E1 已經掃過並報了「金鑰走 docker 命令列」那一條。)
還有一個容易誤會的地方值得記:api/guards.py 這個檔名看起來像放守門邏輯的地方,但它裡面一行守門都沒有,只有一支 runtime() 用來取執行期組件。檔案自己的註解有講明這件事(:8-11:「認證守門不在本檔」)。下一個人 grep guards.py 想找授權邏輯會找不到——真正的位置是 assembly.py 的 _guarded 加上 service 層的 _require_*。
問的是:套件對主系統開出的「零件規格」(domain/ports.py),有沒有留下會被誤解的空間?
專案角色守門那三支(IProjectRoleGuard :63-82):規格寫明三支都只回 true/false,由套件自己負責拋錯誤碼。理由寫在註解裡——錯誤碼是套件的對外契約(前端的多語系訊息對著它),讓主系統各拋各的會讓前端訊息掉回英文。這個設計是對的,也確實被遵守(我核過主系統那一邊 core/plugins/evidence_classification.py:110-120:它 catch 住 ForbiddenError 然後 return False,沒有自己往外拋)。
is_any_project_manager 的語意(「租戶內任一專案的管理者」)規格有寫清楚,並註明「租戶範圍由資料庫隔離鎖」。
🔴 IEvidenceStorage.stage_to_dir 這一項卡片點名要記給下一棒(ports.py:238):規格本身沒有寫「傳進來的檔案編號必須屬於這個租戶」。我開主系統那一邊核對過實際實作(core/plugins/evidence_classification.py:331-361),結論與卡片檔頭的自陳不同——實作裡有跨租戶防呆:
拉檔前先擋越租戶:本方法跑在背景執行緒(無 RLS 收斂),少了這道就能靠猜 uid 把別租戶的檔拉進自己的分類工作目錄。
程式碼是 :354-357:取出每個檔案的擁有租戶編號,跟傳進來的租戶編號比,不一樣就拋 403。所以這一點實作是守住的,但規格書沒寫——下一個寫別的實作的人可能不知道要做這道。這是文件缺口不是資安缺口,記給主系統接線那一棒參考。
IAiProviderConfig.container_env(:104-116):規格明寫「套件只問哪幾家可用,不碰金鑰值」。主系統那一邊的實作(:186-203)確實只放這次要用的那一家的那一把,註解寫明「不是把幾家的鑰匙全倒進容器:多給一把就是多一份會隨容器外洩的憑證」。規格與實作一致,而且方向是對的。
問的是:這張寫死在程式裡的型號表(llm_models.py)有沒有問題?
這是一支純資料檔,沒有安全疑慮——沒有外部輸入、沒有查詢、沒有寫入。我核了卡片問的三件事:
spec_for 查不到時回什麼(:80-85):回 None,由呼叫端擋下。卡片提到的 f8fcde4 那次改動(不再硬退 anthropic)確認在這個版本裡——spec_by_model_id(:88-95)在兩家出現同名型號時回 None 而不是猜一家,註解寫明理由(猜錯的症狀是整批送去錯的供應商,比明確退回預設更難查)。supports_vision:四個型號目前全是 True。碼表註解提醒「不支援圖片的型號遇到圖片證據要明確標示,不可靜默跳過」,實際執法在容器端(不在本棒)。low/medium/high,註解說明兩家 API 其實還收更高檔位但刻意不開給使用者(成本倍數成長、準確度邊際遞減)——這是產品決策的紀錄,不是缺口。順便查到的事(記為觀察 B):設定表有 provider_default 與 model_default 兩欄,畫面填得出來、也存得進資料庫。但我 grep 了分類流程實際怎麼用設定——_resolve_run_params(evidence_batch_service.py:1286-1326)只讀了 effort_default,沒有讀 provider_default 與 model_default。程式自己的註解也承認了:
供應商/模型的 profile 那一層(framework_version_chain 沿鏈解析)尚未接上,接上之後插在「批次上的設定」與「內建預設」之間。
這不是資安問題,是功能沒接完——使用者在設定裡選了「預設用 OpenAI」,實際跑分類時還是會落到批次自己的設定或內建預設。症狀是「我明明設了怎麼沒用」。記在這裡給 FR-107 的後續參考。
要分兩層講,這兩層的可信度差很多:
第一層:「這 16 個檔案裡有沒有我漏掉的洞?」——中等偏可信。
正面的依據:驗證機制完整跑完了(驗證章 verified),三位檢查員全部投了票,沒有人因為額度用完而失聯;而且卡片列的七個重點我全部逐項開檔核過,不是只靠工具。守門那三道(程式層的 _require_settings_manager、資料庫層的 RLS 寫入三條、插件層的 25 支路由包裹)我是一支一支數過的。
要打折的地方:工具的兩位研究員視角很窄,兩位提的是同一條、同一類(守門缺失),這代表它們沒有從其他角度看過這批檔案。零發現有一部分是「這批檔案確實乾淨」,也有一部分是「工具只從一個角度看」。第二部分由我的人工查證補了,但人工查證是照卡片的七個重點走的——卡片沒想到的角度,這一棒也沒查到。
第二層:「AI 分類設定這整件事安全嗎?」——這一棒答不了。
因為金鑰解析鏈的本體不在本棒範圍。「租戶的鑰匙 → 原廠的鑰匙 → 環境變數」這三層退路怎麼查設定、有沒有可能在無脈絡時挑到別租戶的那一列,本體在主系統的 ai_provider_key_resolver.py(199 行)與 adapter 那一段。本棒只查得了「套件這一半有沒有把鑰匙或『誰有鑰匙』露出去」——答案是沒有。另一半要等主系統接線那一棒。
另外,設定被消費的那一端(evidence_batch_service.py 怎麼把人設寫進給 AI 的指令檔)屬於 E2 的範圍,E2 已經掃過並報了相關的事(證據檔內文可對 AI 下指令那條在 E1)。本棒只確認了「設定寫得進去的是誰」。
| 項目 | 數值 |
|---|---|
| 掃描工具 | Claude Code claude-security plugin 0.10.2.3 |
| Run ID | wf_ea23b9f1-1a0 |
| 報告目錄 | jedi-evidence-classification/CLAUDE-SECURITY-20260919-072959/ |
| 驗證章 | CLAUDE-SECURITY-REVISION-955e40964baa-dirty.json |
| 掃描版本 | 955e40964baa3cfc0e8766078db7d65075d3c50b(branch feature/review) |
| dirty | true(工作區有未追蹤的 .claude/ 目錄,非範圍內檔案) |
| mode/effort/focus | scan/low/attack-surface |
| 範圍 | 16 檔 1,850 行 |
| 研究員派出/回報 | 2/2 |
| 候選數 | 2(去重後 1) |
| 面板票數 | 3(=候選 1 × 3 位檢查員),全數投出,無漏投 |
| 通過門檻的發現 | 0(唯一候選 0 票贊成、3 票反對) |
verification.status |
verified(照 stamp 原文抄;意思是「驗證程序完整跑完」,不是「程式證明無漏洞」) |
| 被上限砍掉的候選 | 0 |
| 未被審的候選 | 0 |
| 耗時 | 約 69 分鐘(4,143 秒) |
| agent 總數 | 5(2 研究員 + 3 檢查員),全部完成、零錯誤 |