本卡屬 FR-186(Agent 本體資安掃描第二輪),第 3 批 X2:執行紀錄、本機上傳槽、工具參數白名單(Agent repo,12 檔/約 1050 行)。只掃不修。工作坊用
.claude/workshop-prompts/dispatch-<本卡號>.md當開場 prompt 直接啟動掃描。
用 Claude Code 官方 claude-security plugin 掃 Guidant AI Agent(repo evidence-agent)的「執行紀錄、本機上傳槽、工具參數白名單」,找出資安問題,寫成 PM 與新手工程師都看得懂的報告。只找問題、不修問題。
FR-177 掃過(舊卡 CM-3520),之後有改動;這次重掃要回答兩件事:上次修的有沒有守住、新改的程式有沒有新洞。 範圍按業務模組垂直切(入口→流程→資料),權限漏洞常在層與層的接縫上。
guidant_agent/scan/app/local_runs.py
guidant_agent/scan/app/scan_input.py
guidant_agent/scan/app/probe_runner.py
guidant_agent/scan/app/sync_ports.py
guidant_agent/scan/app/catalog.py
guidant_agent/scan/adapters/local_runs_repo.py
guidant_agent/scan/adapters/scan_input_files.py
guidant_agent/scan/domain/local_run.py
guidant_agent/scan/domain/summary.py
guidant_agent/scan/domain/tool_params.py
guidant_agent/scan/migrations.py
guidant_agent/scan/ports/scan_input_slots.py
檔數 12、約 1050 行。驗檔數:git ls-files -- guidant_agent/scan/app/local_runs.py guidant_agent/scan/app/scan_input.py guidant_agent/scan/app/probe_runner.py guidant_agent/scan/app/sync_ports.py guidant_agent/scan/app/catalog.py guidant_agent/scan/adapters/local_runs_repo.py guidant_agent/scan/adapters/scan_input_files.py guidant_agent/scan/domain/local_run.py guidant_agent/scan/domain/summary.py guidant_agent/scan/domain/tool_params.py guidant_agent/scan/migrations.py guidant_agent/scan/ports/scan_input_slots.py | grep -v /tests/ | wc -l 應為 12。scope 外的檔不要當發現報;為核對呼叫端翻範圍外的檔可以,報告標「只為查證」。
首腦標的思考起點,不是檢查清單。掃完後 runner 逐條對一遍:工具沒報的,開檔看一眼寫「人工查過:成立/不成立/為什麼」。FR-177 的人工補查抓到的問題不比工具少。(以下沿用 FR-177 舊卡的重點,行號是舊版、以檔名與函式名為準。)
scan_input.py:81-111 本機上傳票:issue_local_slot 發票、consume_local_token 只用一次且綁 scan_uid(:108)——票存在記憶體 _slots(),多 worker 時發票與驗票在不同行程會怎樣(正常部署 8444 單行程,確認);票的有效期多長、max_bytes 多少;:124-130 local_upload(scan_uid, sub) 有驗 slot.sub != sub——好,但 find_local_input 的路徑拼法呢。scan_input_files.py 與 scan_input_slots.py:SAFE_DIR_NAME、is_safe_uid、find_local_input(scan_uid, file_name)——file_name 是使用者給的,落地檔名有沒有 secure_filename;purge_expired_inputs 多久清一次、沒清掉的檔會不會被下一個 scan 撿到。local_runs.py:338 行:enqueue(kind, tool, selection, started_by, job, targets) 之後 params 原樣存 DB 再原樣交 connector——params 裡有沒有可能含帳密(例如使用者在主控台填的一次性密碼)進了 local_runs.params 這個明文欄位;finish 寫的 summary 有沒有過遮罩;列表查詢依 started_by 過濾嗎。local_runs_repo.py:22-47:全部參數化(:uid 形式)——好,確認沒有任何一處用 f-string 拼 SQL;targets/params 存 JSON 字串,讀回時 json.loads 有沒有包例外。probe_runner.py(76 行):跑的是什麼探測、目標從哪來、走 shared/timeouts.run_cmd 嗎(外部指令唯一出口);有沒有繞過 run_cmd 直接 subprocess(守衛測試應該擋,確認)。scan/__init__.py:153 行 模組註冊:services() 單例持有哪些狀態;sync_ports.py 從 sync 拿 target_authorizer——掃描前 check() 是不是每條路都會過(手動掃描、主系統派任、探測三條)。scan/migrations.py:local_runs 表有沒有存不該存的欄位(帳密);migration 版號是否與其他模組撞號(全域共用 schema_version)。tool_params.py 預設拒絕、profile 只收 profile:<uid>——確認修法還在、沒被後來的 commit 弄回去、也沒有旁路。FR-177 25 棒報告在 Agent repo docs/security-scan/FR-177/scan-*.md,已登記的 22 條在主系統 repo docs/features/security-scan-consolidated/README.md §3.1 第 219~240 項(全部已修)。已修而且修法成立的不重報;修法不完整、或同一族換個欄位又出現,才報並註明對應項次。