Bible Network Crypto DeFi Onchain RWA AI Agent Stablecoin Chain SAFU CryptoTax DeFAI AGI Claude Me Claude Skill Claude Design Claude Cowork
獨立知識媒體
與任何項目無關聯
學會用 Claude,每件事都做得更好
claudeskill-me.com
最新
用 OpenTelemetry 看 Claude Code 的壓縮與 hook:compaction、hook_execution_complete 與 precompute_reuse 欄位怎麼讀  ·  Bash 權限規則的盲區:deny 擋不住 /bin/rm、bash -c 與 git -C,devbox run * 還會放行內層任何命令  ·  CLAUDE.md 太長了怎麼辦:用 .claude/rules/ 與 paths 讓規則只在碰到特定檔案時才載入  ·  沙盒裡跑 Chromium 出現 No usable sandbox!:--no-sandbox、excludedCommands、allowNestedUserNamespaces 三種解法各放棄什麼  ·  Claude Code v2.1.309:沙盒啟動檔不再在沙盒外執行、denyWrite 經 symlink 失效等一批沙盒與權限缺口修正  ·  auto mode 的 $defaults 陷阱:autoMode.soft_deny 少放一個字串,內建的 force push 攔截規則就整批消失
practice

Bash 權限規則的盲區:deny 擋不住 /bin/rm、bash -c 與 git -C,devbox run * 還會放行內層任何命令

30 秒速讀
Bash 的 deny 規則比對的是命令文字,不是程式;同一個程式換個寫法,規則就看不見它。

完整解析 +
01 · 為什麼發生?

我寫了 Bash(git push *) 的 deny,就不會被 push 了嗎?

不保證。官方文件說它擋 git push origin main,但擋不住 git -C . push origin main 這類寫法。要硬性擋,用沙盒的網路限制或 PreToolUse hook。

02 · 運作原理是什麼?

allow 規則要怎麼寫才不會放太寬?

把 * 放在子指令之後,並連內層命令一起寫。例如用 Bash(devbox run npm test),不要用 Bash(devbox run *),後者連 devbox run rm -rf . 都匹配。

03 · 如何應用

用 WebFetch(domain:...) 限制網域就夠了嗎?

不夠。官方文件明說只用 WebFetch 不能阻止網路存取,Bash 如果被允許,Claude 仍可用 curl 連任何網址;要搭配 deny curl/wget 與沙盒網路白名單。

04 · 我該怎麼做?

不是工程師,一句話懂?

權限規則像門口貼的「禁止攜帶刀具」,只認得常見的拿法;換個藏法就不認得。真要擋,要靠安檢機(沙盒)。

完整內容 +

Bash 權限規則看起來像「允許或禁止某個指令」,但官方權限文件反覆強調:規則比對的是 Claude 寫出的命令文字,不是程式本身。本文整理文件裡幾個最容易讓人以為「已經擋住了」的地方。以下都出自官方權限文件(Configure permissions),我沒有自己逐條測試,所以不加我的實測結論;標明「我的判斷」的是整理。

一、萬用字元放哪裡,範圍差很多

文件的警告是:* 要放在子指令之後。Bash(git log *) 只允許 git log,Bash(git *) 則允許每一個 git 指令。更微妙的是 Bash(git * main):文件的表格說它會匹配 git -c core.fsmonitor=<script> diff main,因為 * 同時代表子指令與前面所有選項,包括會讓 git 執行指定程式的 -c。另外,結尾「空格加 *」的寫法 Bash(ls *) 不匹配 lsof,而 Bash(ls*) 會。

二、deny 規則擋不住「同一個程式的另一種寫法」

文件的表格列出 deny 或 ask 規則擋得住與擋不住的寫法:

  • Bash(rm *) 擋 rm -rf build/,擋不住 /bin/rm -rf build/ 與 bash -c 'rm -rf build/'。
  • Bash(curl *) 擋 curl https://example.com,擋不住 /usr/bin/curl 與 sh -c 'curl ...'。
  • Bash(git push *) 擋 git push origin main,擋不住 git -C . push origin main、git -c push.default=current push origin main、git 'push' origin main。

文件的結論很直接:deny 或 ask 規則涵蓋的是 Claude 通常產生的寫法,不是圍繞該程式的安全邊界;要不依賴命令文字的檔案與網路強制,用沙盒;要用自己的邏輯檢查完整命令文字,用 PreToolUse hook。最後一列「擋不住」的命令由你的其他規則與權限模式決定。

三、複合命令與被剝掉的外殼

  • 規則認得 shell 運算子:&&、||、;、|、|&、&、換行。Bash(safe-cmd *) 不會讓 safe-cmd && other-cmd 通過,每個子命令都要各自匹配。deny 與 ask 則是任何子命令(包括子 shell、命令替換、for 迴圈內)匹配就生效。
  • 比對前會先剝掉固定的外殼:timeout、time、nice、nohup、stdbuf、command、builtin、zsh 的 noglob,所以 Bash(npm test *) 也匹配 timeout 30 npm test。這份清單內建、不可設定。
  • 開頭賦值某些已知安全的環境變數會被剝掉;其他變數的賦值,allow 規則不會匹配,但 deny 與 ask 規則會匹配過任何開頭賦值,所以 Bash(rm *) 的 deny 仍會擋 FOO=bar rm -rf tmp/。
  • 環境執行器不在清單裡:direnv exec、devbox run、mise exec、npx、docker exec 都不會被剝掉,而 Bash(devbox run *) 會匹配 devbox run 後面的任何東西,連 devbox run rm -rf . 都包含。文件建議寫成連內層命令一起的具體規則,例如 Bash(devbox run npm test)。
  • watch、setsid、ionice、flock 這類 exec 外殼,以及帶 -exec、-delete、-fprint 的 find,前綴規則不能自動核准,Manual 模式下仍會詢問。

四、用參數限制 curl 的 URL 很脆弱

文件舉了 Bash(curl http://github.com/ *):想限制只能連 GitHub,但選項放在 URL 前、換成 https、用 -L 跟著重新導向、或先用變數存 URL,都匹配不到。文件的替代方案是:用 deny 擋 curl、wget,再用 WebFetch(domain:github.com) 放行網域;因為 deny 擋不住路徑寫法或 sh -c,要確保的話搭配沙盒的網路白名單;或用 PreToolUse hook。另外文件特別說:只用 WebFetch 並不能阻止網路存取,如果 Bash 被允許,Claude 仍可用 curl 連任何網址。

五、優先順序:deny 先,hook 不能放行過 deny

文件說任何範圍的 deny 都先於 allow:managed 的 deny 不能被 --allowedTools 覆蓋,使用者層的 deny 也擋得住專案層的 allow。PreToolUse hook 的決定不會繞過規則:匹配的 deny 規則仍然擋下,匹配的 ask 規則即使 hook 回 "allow" 仍然詢問;反過來,以 exit code 2 結束的 hook 會在權限規則評估之前就停止呼叫,即使有 allow 規則也一樣。

我的判斷:怎麼用這些資訊

這一節是我的整理,不是官方建議:把 Bash 規則當成「減少詢問的便利層」,而不是「禁止某件事的保證」。真的不能發生的事(刪除、推送、外連),用沙盒或 hook 擋;規則本身要寫成具體到包含內層命令,避免 Bash(git *) 或 Bash(npx *) 這種範圍遠大於你想像的寫法。

資料來源:Configure permissions - Claude Code Docs、Configure the sandboxed Bash tool - Claude Code Docs
圖解
Bash deny 規則擋得住與擋不住的寫法三條 deny 規則各自擋得住的常見寫法與擋不住的繞路寫法,以及被剝除與不被剝除的外殼;真正的邊界要靠沙盒與 hookWhat a Bash deny rule stops, and what it does notRule (deny)StopsDoes not stopBash(rm *)rm -rf build//bin/rm -rf build/ · bash -c 'rm -rf build/'Bash(curl *)curl https://example.com/usr/bin/curl ... · sh -c 'curl ...'Bash(git push *)git push origin maingit -C . push · git -c k=v push · git 'push'Wrappers stripped before matching: timeout, time, nice, nohup, stdbuf, command, builtin, noglobNot stripped: npx, devbox run, mise exec, direnv exec, docker exec (Bash(devbox run *) matches devbox run rm -rf .)For a boundary that does not depend on command text: sandbox (files, network)For full command-text checks: PreToolUse hook (exit code 2 blocks even when an allow rule matches)Claude Skill Me · claudeskill-me.com
歡迎截圖分享,轉載請註明來源
提問
請至少輸入 10 個字
相關詞彙
相關文章
auto mode 的 $defaults 陷阱:autoMode.soft_deny 少放一個字串,內建的 force push 攔截規則就整批消失
practice · 10/23
沙盒裡跑 Chromium 出現 No usable sandbox!:--no-sandbox、excludedCommands、allowNestedUserNamespaces 三種解法各放棄什麼
advanced · 10/23
升級 Claude Code 2.1.299 前先檢查:MCP allow 規則變嚴、Skill 名稱字元被拒、UserPromptSubmit hook 改成先跑
practice · 10/19
Claude Code 的 hook 預設是 fail-open:腳本不存在、逾時、exit 1,守門員都會放行——v2.1.295 的 onFailure: "block" 怎麼用
practice · 10/19
相關新聞