你上個月替 Claude Code 接了兩個 MCP,這週又在 Codex 加了一個 project config;再過幾天,連自己都記不得哪些工具能跑命令、讀到哪裡、會不會連網。Geiger 教學要解決的,就是先把散落在本機的 AI Agent、MCP、Plugin、Hook 與 Extension 變成一份可重跑的曝險清冊。
但先抓住最重要的界線:Geiger 是「設定層的 X 光」,不是「執行中的監視器」。它能指出某個設定可能執行程式、持有 credential-shaped value、碰到廣泛檔案或網路;它不能證明當下的 sandbox 真正生效,也看不到遠端 MCP 下一秒做了什麼。
這篇會用 Geiger v0.2.1 的官方合成 fixture,帶你安全完成第一次掃描、逐項人工核對、保存 JSON baseline,再故意新增一個假 MCP,驗證 --diff 與 --strict 如何報警。最後,我們會把它接成定期稽核,並揭露 AlphaLab 實測發現的一個重要紅線:原始報告仍應視為敏感檔案,不能直接貼進 Issue、Slack 或 AI 對話。
先說結論:可信清冊不是一次掃描
可信曝險清冊=自動掃描+證據路徑人工核對+固定 baseline。
自動掃描回答「哪裡值得先看」;證據路徑讓你回到 Claude Code、Codex 或 MCP 的真實設定;baseline 則回答「今天和上次批准的狀態差在哪裡」。只做第一項,會把保守標籤誦讀成事實;只做人工記憶,三週後通常就失效;只做 diff,又可能把一份原本就危險的狀態永久合法化。
Geiger 是什麼?它到底掃到哪一層
Geiger 是 Atomburst 開源的 Node.js CLI。依 v0.2.1 README,它會在已知設定位置盤點 AI Agent、Harness、MCP server、Plugin、Skill、Hook 與瀏覽器擴充套件;一般執行輸出到 terminal,只有你指定 --json 或 --html 時才寫報告檔。該版本的套件 manifest要求 Node.js 18 以上,沒有 runtime dependency。
「唯讀」要拆成兩件事理解。第一,AlphaLab 檢查 v0.2.1 的CLI source,scanner core 沒有網路或 child-process import,檔案寫入只出現在你明確指定的 JSON/HTML 路徑。第二,npx geiger-scan 仍會依 npm exec 文件下載或讀取 cache,這一步可能連網並寫入 npm cache;所以要把「scanner 只讀設定」和「套件取得完全不碰網路/磁碟」分開。
官方也把限制寫得很清楚:它只找已知 config location,不能觀察 runtime behavior、判斷程式是否惡意、還原混淆程式碼或看見其他使用者帳號。這就是為什麼本文把 Geiger 放在 Agent Observability 之前:清冊找出「可能存在的入口」,Trace、sandbox 與外部紀錄才驗證「入口實際做了什麼」。
開始 Geiger 教學前:先做拋棄式測試 profile
不要用第一個陌生 security scanner 直接碰正式家目錄。以下命令適用於 macOS、Linux 或 WSL:先建立權限收緊的暫存目錄,下載官方 repo,固定在 v0.2.1 對應的 commit,跑內建測試,再複製官方的假設定 fixture。裡面的套件、URL 與 API key 都是測試資料,不是你的真實帳號。
set -euo pipefail
umask 077
export GEIGER_LAB="$(mktemp -d)"
export GEIGER_COMMIT='1991e42045bfa636f8e58001141ba25135e2b464'
git clone https://github.com/Atomburstofficial/geiger.git \
"$GEIGER_LAB/geiger"
git -C "$GEIGER_LAB/geiger" checkout --detach "$GEIGER_COMMIT"
test "$(git -C "$GEIGER_LAB/geiger" rev-parse HEAD)" = "$GEIGER_COMMIT"
(cd "$GEIGER_LAB/geiger" && npm test)
cp -R "$GEIGER_LAB/geiger/test/fixtures/home1" \
"$GEIGER_LAB/profile"
mkdir -p "$GEIGER_LAB/empty-work"
cd "$GEIGER_LAB/empty-work"
AlphaLab 在 2026 年 9 月 10 日用 Node v24.15.0 重跑,內建 7 項測試全部通過;這只證明該版本在官方測試涵蓋內符合預期,不是完整安全審計。空白 work directory 可避免順手掃到你原本所在的 repo;實際掃描時也不要使用 sudo/Administrator。若你之後改用 npm 套件,至少固定成 npx --yes geiger-scan@0.2.1,不要讓浮動的 latest 參與 baseline 比對。
--home 只是改 Geiger 的邏輯 home root,不是 OS sandbox。CLI 仍把目前 cwd 納入 project path,部分 detector 也會查平台層 global npm 位置。空白 work directory 只能縮小誤碰範圍;若你把下載的程式視為尚未信任,第一輪應放進拋棄式 VM 或獨立 OS 帳號,並在真正執行 scanner 時關閉網路。
Geiger 教學:5 步建立可重跑的曝險清冊
第 1 步:先保存 baseline,不急著開 strict
痛點:第一次掃描幾乎一定會看到現存的執行能力;直接加 --strict 只會得到 exit 2,卻還沒告訴你哪些是新風險。解法:先用普通模式產生第一份 JSON,再讀摘要與 evidence path。
NO_COLOR=1 node "$GEIGER_LAB/geiger/bin/geiger.js" \
--home "$GEIGER_LAB/profile" \
--json "$GEIGER_LAB/baseline.json"
jq '{generatedAt:.meta.generatedAt,
total:.meta.total,
counts:.meta.counts,
secretCount:.meta.secretCount}' \
"$GEIGER_LAB/baseline.json"
在這份官方 fixture,AlphaLab 得到 10 個 finding、9 個 EXECUTES、2 個 credential finding;不同作業系統或 Geiger 版本可能不同,請以自己的輸出為準。指定的 JSON 路徑若已存在會被覆寫,所以只用新建、權限收緊的報告目錄。若要掃專案層設定,可重複加入 --path /path/to/project。從第一次到之後每一次都要保持相同 --home 與 project path,因為 finding identity 也包含來源路徑;把同一份 profile 搬家,可能被看成移除再新增。

第 2 步:把六種標籤翻成人工問題
痛點:紅色 chip 很像判決書,容易讓人把「可能能力」誤認為「已使用權限」。解法:每個標籤都改問一個可查證的問題:
- EXECUTES:設定會啟動 command、local script、Hook 或 MCP subprocess 嗎?誰觸發、以哪個 OS user 執行?
- HOLDS-SECRETS:Geiger 在 config 的特定欄位或文字中找到 credential-shaped value;那是有效 secret、假字串,還是漏掃的自訂格式?
- BROAD-FILESYSTEM:此類 agent/local MCP 可能觸及單一專案之外;實際可讀、可寫範圍由 client 設定與 OS sandbox 決定。
- BROAD-WEB:瀏覽器擴充套件宣告了廣泛網站權限;核對 host permission、啟用範圍與 native messaging。
- NETWORK:設定或工具會連遠端服務;接著核對 destination、transport、proxy/allowlist 與誰持有 token。
- UNKNOWN-ORIGIN:Geiger 無法把 local path 追到已知 registry/store;它不是惡意判定,而是要求你找 source、hash 與 owner。
一個很重要的反例是 Codex。v0.2.1 的 detector 看見 .codex 後,就先替 Codex CLI 加上 EXECUTES、BROAD-FILESYSTEM 與 NETWORK,再用文字掃描找 secret shape 與 MCP 宣告;它沒有從 sandbox_mode、approval_policy 或 MCP tool allowlist 推導這些 chip。因此 NETWORK 不等於「目前 command network 已開」,BROAD-FILESYSTEM 也不等於「danger-full-access 已生效」。
第 3 步:沿 evidence path 核對真正控制面
痛點:Geiger 告訴你檔案在哪裡,卻不會替你判斷多層設定最後誰勝出。解法:先匯出「名稱、標籤、證據檔」三欄,再逐列回到產品官方文件核對。
jq -r '.findings[] |
[.name,
(.exposures | join(",")),
(.evidence | map(.file) | join(";"))] |
@tsv' "$GEIGER_LAB/baseline.json"
Claude Code 的 user settings 位於 ~/.claude/settings.json,shared project settings 位於 .claude/settings.json,per-user project settings 位於 .claude/settings.local.json;local/user MCP 通常在 ~/.claude.json,project MCP 在 .mcp.json。依官方權限文件,規則依 deny → ask → allow 評估;Bash sandbox 是 OS 邊界,但不會自動 sandbox Read、Edit、WebFetch 或 MCP tools。看到 Geiger 的 agent 級標籤後,至少要另外核對 permission mode、sandbox、額外目錄、Hook command 與每個 MCP rule。
Codex 的 user config 位於 ~/.codex/config.toml,可信專案可載入 .codex/config.toml。依OpenAI Agent approvals 與安全文件,approval_policy 決定何時詢問,sandbox_mode 才決定 command 的 filesystem/network 邊界;approval_policy="never" 本身不等於完整主機存取。再用Codex MCP 文件核對 server command/URL、forwarded env、HTTP headers、enabled/disabled tools 與每個 tool 的 approval mode。
對 MCP 本身也不要把「read-only」字樣當隔離。MCP 2026-07-28 Tools 規格明確要求,tool annotations 在 server 不受信任時也要視為不受信任的 metadata;local stdio server 是由 client 啟動的本機 subprocess,真正權限取決於 client 與 OS 如何限制它。想深入審查 Tool Description 與 Schema,可接著做 MCP Tool Description Injection 六步審計。
第 4 步:只改一項設定,驗證 diff 與 strict
痛點:你要先知道警報真的會響,才敢把它交給排程。解法:只在合成 profile 新增一個假 MCP;下面的 example 套件與 token 不會被執行,Geiger 只是讀設定。
jq '.mcpServers["new-audit-server"] = {
"command": "npx",
"args": ["-y", "@example/new-audit-server@latest"],
"env": {"SERVICE_TOKEN": "fixture-opaque-token-for-test-only"}
}' "$GEIGER_LAB/profile/.claude.json" \
> "$GEIGER_LAB/profile/.claude.next.json"
mv "$GEIGER_LAB/profile/.claude.next.json" \
"$GEIGER_LAB/profile/.claude.json"
set +e
NO_COLOR=1 node "$GEIGER_LAB/geiger/bin/geiger.js" \
--home "$GEIGER_LAB/profile" \
--diff "$GEIGER_LAB/baseline.json" \
--strict \
--json "$GEIGER_LAB/current.json"
export GEIGER_EXIT=$?
set -e
test "$GEIGER_EXIT" -eq 2
jq '{newHot:.diff.newHot,
added:(.diff.added | length),
changed:(.diff.changed | length),
removed:(.diff.removed | length)}' \
"$GEIGER_LAB/current.json"
AlphaLab 的預期結果是 newHot: 1、added: 1,而 --strict 回傳 exit 2。依v0.2.1 CLI 邏輯,單獨使用 strict 時,只要現存清冊有 EXECUTES 或 HOLDS-SECRETS 就回 2;搭配 baseline diff 時,它只對新出現或升級的這兩類 hot finding 回 2。這讓你能監看 drift,不必因已人工接受的 standing finding 永遠紅燈。

第 5 步:修正、複驗,再由人批准新 baseline
痛點:exit 0 很容易被誤用成「自動批准」。解法:先按 finding 類型處理:不認識的 MCP/Plugin 先停用或移除;local script 追到可審查的 source 與 hash;浮動 package 改成固定版本;真正 credential 先撤銷、輪替,再改用 client 支援的環境變數或 secret store;filesystem 與 network 則回到產品控制面縮小權限。
修完後重跑同一個 home/path,人工讀完 .diff.added、.diff.changed 與 .diff.removed。即使 strict 是 exit 0,也不代表沒有任何 drift:刪除 finding 或不屬於 hot escalation 的變化仍值得查。只有 reviewer 確認每一項後,才把 current JSON 複製為下一版 baseline,並記錄 reviewer、日期、Geiger commit 與原因。
而且 v0.2.1 的 diff 實作只比較 finding 身分、exposure 集合與 secret 數量。把一個 credential 換成另一個但數量不變、同一路徑的 script 原始碼改掉、extension 在外部更新,或 remote MCP 後端換版,都可能沒有對應警報。它是有限的 configuration-drift hint,不是 lockfile、完整性證明或 tamper-evident log。
不要把 baseline 當「安全證明」;它是「這一版已有人看過」的收據。真正能改變風險的是最小權限、sandbox、可信來源、secret lifecycle 與 runtime control。要把撤權、歸因和停用做成系統,可搭配 Agent Runtime Controls;若重點是 API key 不進 Context 或 Session Log,則先讀 AI Agent 密鑰安全教學。
如何把 Geiger 接進定期稽核
最安全的第一版不是把真實清冊上傳公共 CI,而是在固定、受控的本機稽核 profile 每週跑一次。報告目錄設為只有 owner 可讀,排程只產生 current JSON 與 exit code;通知只說「有 drift」,不要附完整報告。人工進機器看 diff 後,再決定是否更新 baseline。
#!/usr/bin/env bash
set -euo pipefail
umask 077
export GEIGER_BIN='/opt/geiger-v0.2.1/bin/geiger.js'
export GEIGER_PROFILE='/srv/geiger-audit/profile'
export GEIGER_BASELINE='/srv/geiger-audit/approved.json'
export GEIGER_CURRENT='/srv/geiger-audit/current.json'
NO_COLOR=1 node "$GEIGER_BIN" \
--home "$GEIGER_PROFILE" \
--diff "$GEIGER_BASELINE" \
--strict \
--json "$GEIGER_CURRENT"
這段 script 的 exit 2 可交給 launchd、cron 或內部 runner 發警報;不要在 script 最後自動 mv current.json approved.json。如果團隊一定要用 CI,先確認 runner 是私有且隔離的、artifact 預設不公開、retention 很短、log 不會把 report echo 出來;公開 repo 只放去識別化的合成 fixture。供應鏈面則可接 AI Infra Guard/MCP 安裝前掃描,兩者解決的是不同層。
重要盲點:Geiger 報告本身也可能洩漏資料
這是本次獨立驗證最重要的發現。Geiger v0.2.1 的 redactor source只比對 9 類已知 secret regex;對 JSON 的 env,還會用 key 名稱補抓 opaque value。但這不等於所有 credential 都能被消除。
AlphaLab 在隔離 fixture 放入一個完全合成的 remote MCP URL,格式為 https://demo-user:fixture-passphrase@example.test/mcp;v0.2.1 的分類邏輯把 URL 存進 origin.ref 後原樣顯示。source review 也顯示 Claude detector掃描 server.env,沒有逐項掃描任意 headers.Authorization。因此本文不採用「secret value 絕不出現在報告」這種絕對說法。
- 報告與原始 config 同級保護:本機保存、
umask 077、最短 retention。 - 公開分享前人工檢查 URL、args、origin、notes、路徑與 header;不要只搜尋
sk-。 - 不要把 raw JSON/HTML 貼進聊天機器人、Issue、公開 CI artifact 或截圖。
- 沒有
HOLDS-SECRETS不代表沒有 secret;它只表示 detector 沒找到支援的形狀/欄位。 - 發現真實值外露時,先撤銷與輪替,再處理報告;刪檔不能讓已曝光的 credential 失效。
這不會讓 Geiger 失去用途,但會改變正確使用方式:它是一支幫你縮小人工搜索範圍的年輕工具,不是資料外洩防護產品。掃描沒告警,也不能取代 Claude/Codex 的 sandbox、MCP 最小工具集、網路 allowlist、人工批准與 runtime Trace。
同樣地,0 findings 只能解讀成「這次在可讀、已知、已掃描的位置沒有匹配項」。v0.2.1 的 filesystem helper會把部分讀取錯誤轉成空結果,非標準路徑與無權讀取的設定也可能消失在清冊;它不能證明機器沒有 Agent,更不能證明安全。
五個最常見的 Geiger 教學誤區
- 直接跑浮動 latest:工具更新和設定 drift 混在一起;先釘版本或 commit,再有意識地升級。
- 把 chip 當有效權限:標籤是 detector 的保守分類,不是 sandbox、approval 或 OS policy 的實測結果。
- 把 exit 0 當安全:strict+diff 只 gate 新/升級的 EXECUTES 與 HOLDS-SECRETS,其他 drift 仍要人工看。
- 移動 profile 後直接比:來源路徑參與 finding identity,應保持掃描 root 穩定。
- 公開上傳報告:redaction 有涵蓋邊界;路徑、URL、套件名與未知 secret format 都可能敏感。
如果你還沒建立 Claude Code Plugin 的來源與權限驗收,可先做 Claude Code Plugin 安全驗收;它和 Geiger 的關係很簡單:前者深入判斷一個擴充套件能不能裝,後者持續提醒你機器上已經有哪些入口。
FAQ:Geiger 教學常見問題
1. Geiger 真的完全唯讀嗎?
v0.2.1 scanner core 讀設定並輸出 terminal;只有指定 --json/--html 才寫該檔案。不過 npx 取得套件會連 registry、使用 cache 並寫入磁碟,所以不能把兩件事混為一談。
2. 出現 EXECUTES 就代表惡意嗎?
不代表。Coding agent、Hook 與 local MCP 的正常功能本來就可能執行程式;你要核對的是來源、實際 command、觸發條件、approval、sandbox 與最小權限。
3. 沒有 HOLDS-SECRETS 就可以公開報告嗎?
不可以直接推論。v0.2.1 只認得特定 secret shape 與部分欄位;未知格式、URL credential、header、路徑或內部服務名稱仍可能出現在輸出。
4. Codex 顯示 NETWORK,是否等於 command 可上網?
不等於。Geiger v0.2.1 沒有用你的 sandbox_mode 推導這個 agent 級標籤;請回到 Codex 的 sandbox、workspace-write network 設定,以及 MCP/connector 各自的網路控制核對。
5. strict exit 2 是程式壞掉嗎?
不是。這是 Geiger 用來表示 hot finding 的預期狀態碼。沒有 baseline 時看現存 EXECUTES/HOLDS-SECRETS;有 baseline 時只看新出現或升級的 hot finding。
6. baseline 可以自動更新嗎?
不應該。自動覆蓋會把警報本身洗掉。current report 要由人逐項核對、留下批准紀錄後,才成為下一版 baseline。
7. 可以直接掃公司的正式開發機嗎?
先不要。先在合成 fixture 驗證版本、輸出與保存方式,再依公司政策於隔離、受控的本機 profile 執行;報告需比照敏感設定檔管理。
8. Geiger 能取代 sandbox 或 EDR 嗎?
不能。它盤點設定面的 standing exposure,不監看 process、syscall、network flow 或遠端 MCP runtime。它應該是 sandbox、最小權限、EDR/runtime telemetry 與人工審查之前的一張索引。
給新手的 6 個重點
- Geiger 是設定層 X 光,不是 runtime 監視器。
- 第一輪先用官方合成 fixture,固定 v0.2.1/commit,再碰受控的真實 profile。
- EXECUTES、NETWORK、BROAD-FILESYSTEM 是待核對線索,不是有效權限判決。
- 用同一個 home/path 建 baseline;只改一項設定,確認 diff 與 strict 真的會報警。
- exit 0 也要人工讀完整 drift,baseline 絕不自動升級。
- 把 raw report 當敏感資料;無告警不代表無 secret,也不代表 runtime 安全。
接著閱讀
左右滑動查看更多推薦
結語:今天先留下第一張可比較的 X 光片
現在先跑官方 fixture:保存 baseline、加入本文的假 MCP、確認 strict 回傳 2,再打開 JSON 找到 newHot: 1。這個 10 分鐘練習會讓你真的理解工具,而不是只記住六個標籤。
回到開頭的公式:可信曝險清冊=自動掃描+證據路徑人工核對+固定 baseline。等合成流程跑通,再把同一套方法搬到受控 profile,逐項撤掉不認識的入口、縮小留下的權限,並用 runtime evidence 驗證結果。想繼續建立 Agent 開發與安全能力,可瀏覽 AlphaLab AI 專區與 AlphaLab 課程。






