E4 檢查結果:設定與插件殼——分類設定 CRUD/模型碼表/plugin 契約/守門殼(jedi-evidence-classification)

E4 檢查結果:設定與插件殼——分類設定 CRUD/模型碼表/plugin 契約/守門殼(jedi-evidence-classification)

檢查日期 2026-09-19|對應卡片 CM-1950|檢查範圍 16 個檔案 1,850 行

§1

🔴 一句話結論

這一棒範圍內沒有找到任何資安漏洞——工具提的唯一一條被三位檢查員一致駁回,我自己把卡片列的七個重點逐項開檔核對後也同意:守門、租戶隔離、插件接線這三道該擋的都擋住了。

白話講這棒在查什麼:「AI 分類設定」就是客戶用來告訴 AI「你是誰、怎麼判、什麼算證據」的那一份設定,它管的是整個框架版本底下所有專案的 AI 行為。所以要問三件事——誰能改它(不能是任何人)、看得到多少(別的客戶的人設與提示詞是客戶的稽核方法論,不能外流)、套件掛進系統時零件缺了會怎樣(該拒絕啟動,不能靜默放行)。三件都查了,都沒問題。

唯一值得決策者知道的一件事,但它不是漏洞:查「這個租戶有哪幾家 AI 可以選」的那支端點,確實沒有像它隔壁四支一樣要求管理員身分——任何登入者都打得到。三位檢查員一致判定這不算漏洞,理由是它回的只有「anthropic」「openai」這種廠商名字加上一張寫死在程式裡的公開型號表,沒有金鑰、沒有網址、也拿不到別的客戶的資料;而且前端的分類操作畫面本來就會呼叫它來填下拉選單,那些畫面的使用者是專案成員而不是管理員,真的加上管理員檢查會把正常功能擋掉。我開檔核對過這三點都屬實,同意這個判定。詳見下方「逐項查證②」。

§2

這一棒在檢查什麼

證據自動分類要用 AI,而「用哪一家的 AI、哪個型號、要它想多深、要它扮演什麼角色、怎麼判斷算不算證據」這些,客戶可以自己設定。這一棒看的就是這份設定的管理後台那一半,加上整個套件怎麼掛進系統的那層骨架。

十六個檔案分成三組:

  • 設定的建改刪查(7 檔):畫面上「新增一份設定/改它/刪掉它/列出來看」背後的那一整條路,從網址進來到寫進資料庫,加上建表腳本。
  • 型號清單(1 檔):一張寫死在程式裡的表,記著「有哪些 AI 型號、哪個看得懂圖片、哪個是預設」。
  • 插件骨架(8 檔):這個套件是以「插件」形式掛進主系統的——它自己不知道「誰是管理員」「檔案存哪裡」,這些都要主系統提供。骨架這一層負責檢查主系統有沒有把該給的零件都給齊,沒給齊就拒絕掛載。所有端點的登入檢查也是在這一層統一套上去的。

選它當第四棒的理由:設定管所有專案的 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 這個版本裡。

§3

Coverage

十六個檔案全部讀完,就是範圍給的全部。

不在本棒範圍、但這份報告的結論依賴它們(我開檔查證時讀了,屬於對照不屬於審查):

  • 主系統側的 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 被駁回,沒有候選遺失、沒有候選未被審、沒有被上限砍掉。

工具沒有執行任何程式碼:沒有打過任何端點、沒有跑測試、沒有連過資料庫。下面所有判斷都是讀原始碼推出來的。

工具的偏食:兩位研究員都只盯「守門有沒有漏」這一類,而且兩位提的是同一條。卡片列的七個重點裡,工具只碰到①②的一小角,③④⑤⑥⑦完全沒報,全部由我逐項開檔補查(見下方「卡片重點逐項查證」,每項都標明是工具報的還是人工查的)。

§4

掃到什麼(總覽)

範圍內淨新增零條。 沒有發現需要開修正卡的資安問題。

工具提出、檢查員駁回的那一條記錄如下(不計入發現數):

候選 工具評的嚴重度 檢查員判定 為什麼駁回
查可用型號的端點沒有管理員檢查 低 3 票全數駁回 回的是廠商名字加一張公開型號表,沒有金鑰也沒有別人的資料;而且前端的分類操作畫面本來就要呼叫它,加了檢查會擋掉正常功能

我另外記下兩件不是資安問題、但下一任接手的人應該知道的事(都不開卡):

# 是什麼 為什麼不是資安問題 記在哪
A 設定表的「AI 人設」與「判斷指引」兩個欄位沒有長度上限,而它們會被寫進給 AI 的指令檔 寫得進去的只有租戶管理員(自己人),寫進去的內容只影響自己租戶自己的分類結果;這是「管理員可以把自己的 AI 設定寫得很爛」不是「外人可以動手腳」 下方逐項查證③
B 設定裡的「預設廠商/預設型號」兩個欄位存得進去、畫面填得出來,但分類真的跑起來時沒有人去讀它們(只有「預設思考深度」被讀) 是功能沒接完,不是資安缺口——使用者設了沒作用,症狀是「我明明設了 OpenAI 怎麼還是跑 Anthropic」 下方逐項查證⑦
§5

Findings

無。

§6

卡片重點逐項查證

卡片列了七個重點。工具不照清單走,所以每一項我都回頭核了一次,下面標明哪些是工具碰過的、哪些是我人工開檔查的。

① 守門與放寬後的邊界(人工查證,工具只碰到一角)

問的是:設定的建改刪查這五支,到底誰打得到?

查到的: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(),跟隔壁四支不一樣,所以任何登入者都打得到。

三位檢查員一致駁回,我開檔核對三個駁回理由,全部屬實:

  1. 回的內容裡沒有金鑰也沒有網址。 我追到主系統的 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」,答案是不會。

  2. 拿不到別的租戶的東西。 租戶編號來自呼叫者自己的登入脈絡(:125 呼叫 _require_identity(),:303-311 從 get_user_context() 取),不是從網址或請求內容來的,所以沒有「改個數字看別人的」這種玩法。

  3. 前端的正常功能依賴它。 我在前端 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 的後續參考。

§7

這份結果可信到什麼程度

要分兩層講,這兩層的可信度差很多:

第一層:「這 16 個檔案裡有沒有我漏掉的洞?」——中等偏可信。

正面的依據:驗證機制完整跑完了(驗證章 verified),三位檢查員全部投了票,沒有人因為額度用完而失聯;而且卡片列的七個重點我全部逐項開檔核過,不是只靠工具。守門那三道(程式層的 _require_settings_manager、資料庫層的 RLS 寫入三條、插件層的 25 支路由包裹)我是一支一支數過的。

要打折的地方:工具的兩位研究員視角很窄,兩位提的是同一條、同一類(守門缺失),這代表它們沒有從其他角度看過這批檔案。零發現有一部分是「這批檔案確實乾淨」,也有一部分是「工具只從一個角度看」。第二部分由我的人工查證補了,但人工查證是照卡片的七個重點走的——卡片沒想到的角度,這一棒也沒查到。

第二層:「AI 分類設定這整件事安全嗎?」——這一棒答不了。

因為金鑰解析鏈的本體不在本棒範圍。「租戶的鑰匙 → 原廠的鑰匙 → 環境變數」這三層退路怎麼查設定、有沒有可能在無脈絡時挑到別租戶的那一列,本體在主系統的 ai_provider_key_resolver.py(199 行)與 adapter 那一段。本棒只查得了「套件這一半有沒有把鑰匙或『誰有鑰匙』露出去」——答案是沒有。另一半要等主系統接線那一棒。

另外,設定被消費的那一端(evidence_batch_service.py 怎麼把人設寫進給 AI 的指令檔)屬於 E2 的範圍,E2 已經掃過並報了相關的事(證據檔內文可對 AI 下指令那條在 E1)。本棒只確認了「設定寫得進去的是誰」。

§8

執行概況

項目 數值
掃描工具 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 檢查員),全部完成、零錯誤