想讓 Chromium 在 Claude Code 的沙箱裡保住它自己的沙箱,你得先把 Claude Code 沙箱的一面牆拆掉。

聽起來像笑話,但這是 Claude Code 2.1.305 新增的設定 sandbox.allowNestedUserNamespaces 在官方文件裡的真實形狀。先交代邊界:我只讀了官方文件、CHANGELOG 和一則 GitHub issue,沒有在任何機器上開過這個設定,也沒有實際跑過 Chromium、unshare 或 podman。所以文中「開了之後會怎樣」,全部只是官方原文的轉述,不是我的實測。

牆裡面又想蓋一間房

沙箱的邏輯是把指令關在一個小房間裡。問題是有些程式自己也想蓋房間,Chromium 就是,它要用 user namespace 把網頁內容再關一層。蓋房子的人得有施工權限,而 Claude Code 的沙箱預設不給。

文件寫得很直接。在 Linux 和 WSL2 上,沙箱內的指令預設不能建立 user namespace,依賴它的工具會失敗,官方列了三種症狀:

工具 沙箱裡看到的症狀(官方原文)
Chromium No usable sandbox!
unshare -U true unshare: unshare failed: Operation not permitted;開了 allowAllUnixSockets 時,可能改印 No space left on device
rootless Podman cannot clone: Operation not permitted,或更早就因 read-only file system 停住

出處是 Claude Code 沙箱文件 的 “Chromium or rootless Podman fails inside the sandbox on Linux” 一節。

GitHub 上有一則剛開的 issue 正好是這個牆的現場:anthropics/claude-code#103811。回報者在 WSL2 上,沙箱內 /proc/sys/user/max_user_namespaces 讀出來是 0,同一台機器的一般 WSL 終端機是 30997,unshare -Ur true 也只有後者過得了。他寫得很明白:他們要的是 Chromium 自己的沙箱留在 Claude 的沙箱裡,Chromium 的 log 建議關掉它自己的沙箱,他們不接受。

這則 issue 建立於 2026-10-20 17:31 UTC。2.1.305 的 npm 發布時間是 2026-10-20 19:29 UTC,換成台灣時間是 10 月 21 日凌晨 3 點多,比 issue 晚了約兩小時。我沒有證據這兩件事有因果關係,不能寫成「因為這則 issue 才新增了開關」。我能確定的只有:截至 10 月 22 日,這則 issue 仍是 OPEN,我查的時候,這則 issue 下面沒有留言。

三條修法,各付各的

文件給了三條路,我把它們原文的代價攤開來看。

修法 保住什麼 丟掉什麼(官方原文)
瀏覽器加 --no-sandbox Claude Code 的沙箱不動 瀏覽器 runs web content without its own sandbox
sandbox.excludedCommands 加 podman * 之類 指令能跑 符合的指令 run outside the sandbox with your full access,而且 Claude 可能在執行前先改你工作目錄裡的腳本
allowNestedUserNamespaces 設 true Chromium 或 Electron 保住自己的沙箱;也能跑巢狀 bubblewrap 或 unshare 見下一節

前兩條的代價一眼看得懂:要嘛少一層瀏覽器的牆,要嘛整條指令光明正大走到沙箱外。第三條看起來最折衷,兩邊的牆都留著。

這正是我覺得它最容易讓人放鬆戒心的地方。

最像折衷的那條,官方放了 WARNING

文件在同一節放了一個 WARNING,原文是:

“If you set allowNestedUserNamespaces to true, you turn off a security boundary: code from a sandboxed command can end up running outside the sandbox.”

下一段接著說,不要靠沙箱的任何限制(包括 protected paths 和 credentials.files 條目)去擋一個惡意指令;在 auto-allow 模式下,那個指令可以不經權限提示就跑起來。如果你的組織有資安團隊,開之前先問他們。

CHANGELOG 對這個設定的說法也一致,2.1.305 那一行寫的是:它讓沙箱內的指令能建立 user namespace,同時「this lets them get around the sandbox’s file protections」。

至於為什麼建立 user namespace 就會讓程式碼跑到沙箱外,文件只寫結論,沒寫機制。我也不打算自己補一套機制出來,那就變成編的了。我能轉述的,只有「官方認為這是拆掉一道邊界」。

所以回到開頭那句話。為了讓一個沙箱留著,把另一個沙箱的牆拆掉。如果你的 Chromium 跑的是你信得過的測試指令,這個交換也許划算;如果指令你沒把握,文件的意思是別指望沙箱幫你擋惡意指令。

這個開關的三個邊角

有三處容易誤會,都有官方原文,但各自屬於不同層級或不同情境,我分開寫。

第一,它單獨解不了 rootless Podman。設定參考頁說,rootless Podman 或 Buildah 要改用 excludedCommands,因為沙箱還會用別的方式擋它們;沙箱文件寫的是 “This setting alone isn’t enough”。有意思的是 CHANGELOG 同一行的括號寫了「(Chromium, rootless podman)」。兩處對 podman 的說法不一致,我不替官方調和,兩段原文並排放這裡,實際要不要用請以你的版本文件為準。

第二,寫在專案設定裡沒用。這個設定的 scope 是 user or managed:true 只從 ~/.claude/settings.json、--settings 傳入的 JSON 或 managed settings 算數;專案的 .claude/settings.json 和 .claude/settings.local.json 裡的 true 會被忽略。管理者想擋它,在 managed settings 設 false,false 則是任何檔案都算。所以一個 repo 沒辦法自己幫你把這道牆拆掉,這點我覺得設計得對,也呼應之前寫過的 server-managed settings 那套「誰有權鎖」的邏輯。另外,如果 session 設了 CLAUDE_CODE_SUBPROCESS_ENV_SCRUB 為 1,不管哪個來源的 true 都會被忽略。

第三,unshare 開頭的指令。文件對 excludedCommands 的說明是:以 unshare 開頭的指令,不管你列了什麼 pattern,都留在沙箱內,因為 unshare 可以啟動任何其他程式。也就是說,想靠 excludedCommands 放行 unshare 這條路是封死的;文件把「跑巢狀 bubblewrap 或 unshare」歸給第三條修法。至於開了 allowNestedUserNamespaces 之後 unshare 實際跑不跑得起來,這件事我只讀到上面這些,沒有驗證,不下結論。

設定長什麼樣

官方範例本身很短,這是設定參考頁給的,放在 ~/.claude/settings.json:

1
2
3
4
5
6
{
"sandbox": {
"enabled": true,
"allowNestedUserNamespaces": true
}
}

走 excludedCommands 那條路,文件的範例是這樣,注意 pattern 要用 * 結尾,因為它的語法跟 Bash(...) 權限規則一樣,沒有萬用字元就是完全比對:

1
2
3
4
5
6
{
"sandbox": {
"enabled": true,
"excludedCommands": ["docker compose *"]
}
}

文件還補了兩句,我覺得比設定本身重要:一條複合指令裡每一段都得符合,npm ci && docker compose build 除非另有 pattern 蓋住 npm ci,否則整條仍在沙箱內;而被排除的指令是以你的完整權限在跑。

想先確認自己是不是真的卡在這道牆,可以拿 issue 回報者用的診斷法,這是他自己的重現步驟,不是官方建議:

1
cat /proc/sys/user/max_user_namespaces

他在沙箱內讀到 0,在一般 WSL 終端機讀到 30997。這只是單一案例,我沒辦法保證你的環境一樣。

兩件別混在一起的事

最後澄清兩個容易跟它混在一起的設定。

enableWeakerNestedSandbox 處理的是另一件事:在沒有特權的容器裡,bubblewrap 掛不了全新的 /proc,會報 Can't mount proc on /newroot/proc,開了它就改成 bind-mount 容器現有的 /proc。文件說它 considerably weakens security,只該在別處已經有額外隔離時用。#103811 的回報者也提到他們沒用它,因為它文件寫的是 Docker 和 /proc,不是 namespace。

Ubuntu 24.04 以上又是一道牆:預設 AppArmor 政策會擋 bubblewrap 建立它隔離需要的 user namespace,可用 sysctl kernel.apparmor_restrict_unprivileged_userns 檢查,回 0 或 No such file 可略過,回 1 要幫 bwrap 補 AppArmor profile。這是「沙箱本身能不能跑」,跟「沙箱裡的子指令能不能再蓋 namespace」是兩層。

帶走一個提問

這個設定逼你回答的其實是一個問題:這個指令,我信不信?

信,就老實用 excludedCommands 讓它走出沙箱,至少你知道自己放行了什麼。不信,就別開,改用 --no-sandbox 之類成本看得見的方式,或乾脆不在 Claude Code 裡跑它。夾在中間、看起來兩邊都顧到的那條,文件偏偏特地放了一則 WARNING。

開了之後到底有哪些路徑會被繞過去,文件沒給範圍,#103811 也沒有官方回覆。所以我的立場是先不開。這個判斷要改,得等兩件事同時出現:文件把被放寬的範圍寫清楚,#103811 也有了官方回覆。在那之前真的要開,先讀完那段 WARNING,再去問你的資安團隊。