FR-114.V3 b4 實打驗證報告——資源上限:只驗被擋、不打垮(24 條,只驗不修)

  • 卡號:CM-2266(母卡 CM-2019)
  • 目標機:190(BE guidant-ai-be:1.21.0b4/FE 同版/agent 1.1.0b2,九容器 healthy)
  • 日期:2026-09-27
  • 性質:產品驗收(非滲透)。每條做法固定三步:讀對應修正卡查「上限值+超限回應碼」→ 送「剛好超過上限一點點」的請求 → 比對實際回應是否等於宣告的回應。等於 ✅/不等於 ❌/190 無資料可測或被前置條件擋到 ⚠️。
  • 打之前查過 190 無人總測:docker logs guidant-api 22:16 之後靜默;每打一條看 docker stats guidant-api。
  • 未打垮 190:全程 guidant-api 記憶體 1.50–1.60GiB 平穩,無任何 201MB/33MiB 級跳升;所有超大檔都在「讀目錄/擋長度」階段被拒,未進解壓/解析。
  • 只讀不改:測試中建的少量資料(一個測試檢測基準、一個資源庫、兩個框架解析單、幾筆失敗的匯入 staging)測完即刪/已 soft-delete;未套 migration、未重啟容器、未動 STG/POC/DEV。
§1

190 環境實況(影響判讀,先讀)

  1. 稽核輪次只有兩個:round 1(closed)、round 2(planning,未啟動稽核)。因此稽核計畫 Word(#176)/稽核紀錄 Excel(#177)沒有「可編輯的輪次」可打——請求在「本輪已結案/尚未啟動」的前置條件就被擋,走不到壓縮炸彈守門。守門本身已在同族 #150/#152 於全域解析入口證實(同一支 check_ooxml_archive)。
  2. admin(平台管理員、root 租戶)登入不走 MFA,POST /login 直接回 access_token(其餘五個租戶帳號要 MFA)。#192、#34 的 /license/upload 需要它。
  3. 檢測基準的並行解析上限(#80)是行程內記憶體旗標:多 worker gunicorn 下,兩個請求落在不同 worker,且測試用小基準毫秒級解析完,API 打不出「同一版正在解析中」的重疊窗——結構正確、行為層無法從外部逼出,打折。
§2

結果表(n=SUMMARY 條號;結果 ✅過/⚠️打折或前置擋/❌破)

n CM 一句 結果 證據
16 2059 特製流程圖走訪算不完 ⚠️ POST /flow-engine/flow-templates/validate 送 30 gateway 深鏈 → schema/topology 先判 gateway_missing_condition(HTTP200 valid:false),走不到走訪深度上限(100節點/8層)。上限在 create/起輪次的走訪端,需 schema 合法的惡意範本才觸得到,API 構造不出——同 V1 #40/#87/#88 打折原因
21 2064 AI 儀表板無限重試 ✅ POST /ai-dashboard/auto-generate ×5:第 4、5 次 429 AI_DASHBOARD_429001(上限 3/分鐘,因一次生成打兩次外部 AI)。前 3 次 200
34 (無卡,共用底層) 1.4MB 授權匯入吃 1GB ✅ POST /license/activation/upload(任何登入者):33MiB base64 payload → 400(0.13s,記憶體平);zlib 炸彈(解開 17MB)→ 400(1.2s)。log 確認 _verify_signed_license 擋下。守門在 engine._unpack_payload(解碼前擋 32MiB 字串+有界解壓 16MiB),例外被 verify_payload 包成 LICENSE_400002(不是原始長度碼,屬預期包裝)。/license/upload 另需平台管理員(403 GRC_403060)
70 2050 開始掃描多存明文帳密 ✅ DB 唯讀:select count(*) from compliance.agent_tasks where params ? '_credentials' = 0;全表最新一筆 20:22。無殘留(修正卡本就查得 DEV 為 0)
76 2057 網址規則包繞過壓縮炸彈三上限 ✅ file 型上傳 500MB 解壓炸彈規則包 → 400 DETECTION_TOOLS_400010「Profile archive failed safety checks」(上傳即擋,記憶體平)。網址型的三道上限與 file 型下沉到同一 _read_entries/archive_limits,同支守門
77 2057 一萬檔上限展開後才數 ✅ 上傳 10,001 entry 的規則包 → 400 DETECTION_TOOLS_400010(讀 zip 目錄即擋,未展開進記憶體,記憶體平)
80 2058 重新解析去重與總量上限 ⚠️ POST /detection-tool-profile-versions/<v>/extraction 併發 ×2 與 ×12 均 200——並行旗標是行程內記憶體、多 worker 下打不出重疊窗,小基準毫秒解析完。結構(is_inflight→409018/has_capacity→409019)在源碼確認存在,行為層打折
81 2058 換工具沿用超大網段展開 ✅ POST /detection-tools/configs/<c>/test-connection 送 33 台 → 400 DETECTION_TOOLS_400019「本次 33 台,上限 32 台」;送 32 台 → 200。單次主機數上限生效(換工具重驗與展開端 65,536 絕對上限同支邏輯)
83 (無卡,共用底層) 清單頁 page_size 超大撈整表 ✅ 多支列表(detection-tool-profiles/list、project-summary-reports、oscal-frameworks)pager.page_size=1000→200、1001/100000→400 COMMON_400001。MAX_PAGE_SIZE=1000 在共用 PagerSchema,一處蓋全站
94 2064 聊天框無長度無次數上限 ✅ POST /ai-chatbot:5000 字訊息 → 400 AI_BOT_400001「訊息過長」(上限 4000);短訊息 ×12 → 第 11、12 次 429 AI_BOT_429001(上限 10/分鐘)
106 (無卡,共用底層) 日誌分區失效、保存期無效 ✅ DB 唯讀:api_logs/system_logs 各有 2026_09/10/11 三月份分區+default;備用表 *_default 皆 0 筆;排程 log_partition_maintenance (daily 03:30 UTC) 已在 APScheduler 清單;maintain_log_partitions() prosecdef=t(SECURITY DEFINER,owner cmmgr)→ 不再因權限每晚失敗
108 (無卡,共用底層) 半夜清理程式靠「無身分給最高權限」 ✅ 源碼確認 core/scheduler.py 兩支清理(job_binding_orphan_cleanup/framework_parse_job_cleanup)皆以具名 system_context("...") 執行;APScheduler 啟動清單列出兩者(daily 03:10/01:00 UTC)。M20-4 已複查改具名系統身分+反向警語
131 2061/2181/2227 分類壓縮檔炸記憶體、殘留燒額度 ✅ 落地版 guidant-classifier 容器 docker inspect:Memory=2147483648(2GiB)、NanoCpus、PidsLimit=256、逾時 killpg/docker kill 整組砍。分類容器 healthy、55MiB。上限+逾時 kill 在位(實際灌爆屬破壞性、不做,看設定值+容器實況)
136 (無卡,共用底層) 清單頁 page_size 超大(與 #83 同底層) ✅ 同 #83:page_size=1001→400 COMMON_400001;根源同一支 PagerSchema.MAX_PAGE_SIZE=1000
149 2171 不必登入的遮密碼比對卡死 ✅ 不帶 token、打不存在網址送 16/64/65/128KB 攻擊內容:全部 404、0.09–0.18s(修前套件層量到 16KB 171 秒)。DB api_logs 確認 request 被截到 65558 bytes 帶「…[已截斷,原長 N bytes]」。線性時間+64KB 截斷兩層都在
150 2181/2189/2203 SSP Excel 只量壓縮檔不量解開 ✅ POST /ssp-excel-imports/parse 送 201MB 解壓炸彈 xlsx → 解析單 failed GRC_400065(0.4s,記憶體平);送 5,001 段 xlsx → 同 GRC_400065。開檔前讀 zip 目錄擋(200MB/5000 段)
152 2181 SSP Word 只量壓縮檔 ✅ POST /ssp-docx-imports/parse 送 201MB 解壓炸彈 docx → 解析單 failed GRC_422003(0.4s,記憶體平)
154 2171/2181 Excel 版本格一百萬數字卡比對 ✅(隨 #150 同支覆蓋) 版本號截 200 字+位數上限在 version_check.py,與 #150 同一 xlsx 匯入路徑;#150 的 201MB 已在版本檢查前被壓縮炸彈守門擋下,版本格上限為同支後段防線。無獨立可打入口,以 #150 佐證
175 2179/2182 草稿框架版本拿去建資源庫 ✅ POST /oscal/resource-libraries:draft 框架版本 → 412 GRC_412057「框架版本尚未發佈」;published → 200。建庫共用函式在 clone 前擋(一處蓋手動/Excel/Word 三入口)。建的測試庫已刪
176 2181 稽核計畫 Word 解壓炸彈 ⚠️ POST /ap/<ap>/docx-imports/parse 兩個 AP:一個 404 GRC_404038(無對應輪次)、一個 412 GRC_412049(本輪已結案)。190 無可編輯輪次,前置擋在守門前。同支 check_ooxml_archive 已於 #150/#152 證實
177 2181 稽核紀錄 Excel 讀到最後一列 ⚠️ POST /audit-round/<r>/ar-imports/parse:round 2 412 GRC_412043「本輪尚未啟動稽核」。190 無可編輯輪次,前置擋在守門前。串流讀+200 空白列停+5000 列上限在同支解析器(#177 與稽核結果 Excel 共用)
192 2184/2201 CMMC PDF 頁數撐爆記憶體 ✅ POST /oscal-framework-parse-jobs/parse(admin)送 3,001 頁 PDF → 解析單 failed GRC_422004(0.86s、記憶體平;修前 7s/973MB);10 頁 → awaiting_review。log 確認 base_parser_adapter._assert_page_count → OSCAL_V2_400006「PDF 頁數超過上限」(3000 頁上限)。解析單已刪
196 2181/2213 稽核計畫 Word 塞幾萬空白卡比對 ⚠️ 同 #176,稽核計畫 Word 入口在 190 無可編輯輪次、前置擋下。空白壓縮+標題截 2000 字在解析器(CM-2181),與 #176 同入口,一併打折
207 2203 匯入任務 Excel 無上傳檢查 ⚠️/❌ POST /grc/project/<p>/ap/<ap>/jobs/import 送 201MB 炸彈 xlsx → HTTP 500 column ap.uid does not exist(0.5–0.6s,記憶體平)。壓縮炸彈守門在 500 之前跑不到;此 500 是既有缺陷(jobs/import 路徑 SQL 查 ap.uid 欄位不存在),與本卡上限無關、屬另一 bug,建議另開卡。守門本身(同 CM-2181 archive_limits+串流讀)在源碼確認存在,但此入口無法乾淨驗到
§3

統計

  • ✅ 通過 15 條:#21、#34、#70、#76、#77、#81、#83、#94、#106、#108、#131、#136、#149、#150、#152、#175、#192(+#154 隨 #150 同支覆蓋)
  • ⚠️ 打折/前置擋 8 條:#16(走訪端 schema 先擋,同 V1)、#80(並行旗標行程內、多 worker 逼不出重疊)、#176/#177/#196(190 無可編輯輪次)、#207(撞既有 500);#154 以同支佐證
  • ❌ 破 0 條
  • 另發現 1 個既有缺陷(非本卡範圍):jobs/import 路徑 column ap.uid does not exist 500 → 建議另開卡
§4

打折處逐一講明(不報成通過)

  • #16:190 上送不出「schema 合法但走訪爆量」的流程圖——validate 在 topology 層先擋(gateway 缺條件)。走訪深度上限(100 節點/8 層)在 create/起輪次端,需要一份格式完全合法的惡意範本才觸得到,這無法用 API 從外部construct。與 V1 的 #40/#87/#88 同一打折原因。
  • #80:並行控管 extraction_concurrency 是單一行程的記憶體旗標。190 是多 worker gunicorn,兩個 extraction 請求落在不同 worker、各自看到空旗標;且測試基準小到毫秒級解析完,先到的早已 release。要逼出「同版正在解析」重疊窗需在同一 worker 內卡住解析,API 外部做不到。源碼層 is_inflight→409018、has_capacity→409019 確認存在。
  • #176/#177/#196:190 只有 closed 與 planning 兩個輪次,稽核計畫/稽核紀錄匯入都要求「輪次在對應可編輯階段」,請求在前置條件(GRC_404038/GRC_412049/GRC_412043)就被擋,走不到壓縮炸彈守門。守門是四入口共用的同一支 check_ooxml_archive(jedi-compliance-audit),已在 #150(SSP Excel)/#152(SSP Word)於全域解析入口實打證實生效。
  • #207:jobs/import 撞到既有 500(column ap.uid does not exist),發生在檔案守門之前,因此本卡無法乾淨驗到上限。此 500 與資源上限無關,是另一支 bug,建議另開卡處理。