apply-seccompのsetgroups書き込みがPermission deniedで失敗する原因と対処
apply-seccompのsetgroups書き込みがPermission deniedで失敗するLinuxサンドボックス不具合の2つの原因説と、allowAllUnixSocketsなど回避策の代償を扱います。
Claude CodeのLinuxサンドボックスを有効にすると、すべてのBashコマンドが次のエラーで失敗することがあります。
apply-seccomp: write /proc/self/setgroups (nested userns is capability-restricted; caller must provide CAP_SYS_ADMIN): Permission denied結論から言うと、network.allowAllUnixSockets: trueを設定すると、サンドボックスを残したままこのエラーを避けられます。sysctlでAppArmorの制限を外しても直らないことが多く、修正は入っていません。
GitHub Issue #43454は、Claude Code 2.1.92でapply-seccompヘルパーが必ず呼ばれるようになってから、Ubuntu 24.04以降で起きている不具合です。Issueは2026年4月4日に登録され、2026年8月24日のコメントでも同じ失敗が報告されています。原因の説明が2つに割れており、サンドボックスを丸ごと切らずに済む回避策がnetwork.allowAllUnixSocketsだという点が、この記事の中心です。
似た場面で起きるunshare(CLONE_NEWUSER)のEINVAL失敗とは原因も対処も別物です。サンドボックスそのものの有効化・無効化の挙動はsandbox.enabledはClaude CodeのBashコマンドを隔離する設定で確認できます。
/proc/self/setgroups書き込みが拒否される仕組み
sandbox.enabledが有効なLinux環境で、Claude Codeはapply-seccompという名前のヘルパーを使い、ユーザー名前空間(user namespace)を作ってからBashコマンドを起動します。ユーザー名前空間の内側では、UID/GIDのマッピングより先に/proc/self/setgroupsへdenyを書き込む手順を踏みます。Issue本文の再現コマンドは、この書き込みだけを切り出したものです。
# apply-seccompが内部で行っているのと同じパターン
unshare -U bash -c "echo deny > /proc/self/setgroups"
# → Permission denied
# 先にUIDマッピングを済ませると成功する
unshare -Ur echo testエラー文は「CAP_SYS_ADMIN(Linuxの特権のうち特に広範なもの)が要る」と言っています。ところがIssueのコメントでは、この説明が正しいかどうかで意見が分かれています。
原因は2つの説に割れている
Issueに出ている原因の説明
AppArmorの拒否説
Ubuntuの/etc/apparmor.d/bwrap-userns-restrictが定義するunpriv_bwrapプロファイルが、audit deny capabilityでbwrap配下の子プロセスからCAP_SYS_ADMINを剥がします。apply-seccompもその対象です。kernel.apparmor_restrict_unprivileged_usernsを0にしても直らないのは、制限の場所が別だからだと説明されます。
bwrapの継承説
非特権で動くbwrapが自分のユーザー名前空間にsetgroups=denyを設定し、これは子孫の名前空間でも変えられません。ヘルパーの中でもう一度denyを書く処理が、カーネルに拒否されます。bwrap --cap-add CAP_SYS_ADMINを付けても失敗する比較表が根拠で、bwrapがsetuid rootの環境ではsetgroupsがallowのままになるため、同じ書き込みが通るとされています。
どちらの説でも、kernel.apparmor_restrict_unprivileged_userns=0では直らない点は一致しています。
失敗する書き込みは環境によって異なります。8月18日のClaude Code側のコメントは、カーネルによって失敗するのがsetgroupsの場合もuid_mapの場合もあるが、根本原因は同じだと書いています。同じ日の別のコメントは、カーネル更新の後にunshare -Urがuid_mapの書き込みで失敗するようになったと報告しました。以前は通っていたコマンドです。標準のunprivileged_usernsプロファイルがcapabilityをaudit denyすることが、AppArmor説の根拠の一つになっています。6月22日のコメント(Ubuntu 26.04・kernel 7.0.0-15)も、同じ設定値のまま再現したと報告しています。
自分の環境がこの不具合に該当するか
エラーメッセージが同じでも原因が違うケースがあります。次の順で確かめると、的外れな対処を避けられます。
症状の切り分け
- 1
AppArmorが実際に拒否しているかを見る
監査ログに
unpriv_bwrapの拒否が出ていれば、AppArmor側にも原因があります。 - 2
bwrapの内側で`setgroups`が`deny`になっているかを見る
bwrap --dev-bind / / --unshare-user -- cat /proc/self/setgroupsがdenyを返し、外側のcat /proc/self/setgroupsがallowなら、継承説に当てはまります。 - 3
どちらでもなければ別の原因を疑う
apply-seccompの実行権限の欠落や、コンテナ内の/procマウント失敗は、同じ画面に別のエラーで出ます。後の節で扱います。
sudo dmesg | grep -i "apparmor.*DENIED.*unpriv_bwrap"出力にはprofile="unpriv_bwrap" comm="apply-seccomp" capability=21 capname="sys_admin"のような行が並びます。報告はkernel 6.17.0-14から7.0.0-30まで複数のバージョンにまたがっており、特定のカーネルビルドに限った不具合ではありません。
v2.1.92でサンドボックスのフォールバックが消えた
この不具合は既存のバイナリが壊れたのではなく、新しいヘルパーの導入で表面化しました。CHANGELOGはv2.1.92の変更点を次のように記録しています。
Linux sandbox now ships the
apply-seccomphelper in both npm and native builds, restoring unix-socket blocking for sandboxed commands
v2.1.91で動いていたという報告の中には、サンドボックス自体が起動していなかった環境があります。4月17日のコメントは自環境でsocatが未導入だったと書いています。当時はsocatが入っていないとサンドボックスが黙って無効化され、Bashは素のまま(Seccomp: 0、ユーザー名前空間なし)で実行されていたためです。v2.1.92からはヘルパーがsocatの有無に関係なく呼ばれ、それまで隠れていた失敗が起動エラーとして表に出ました。
公式ドキュメントはseccompフィルターを「任意」と書き、足りなければnpm install -g @anthropic-ai/sandbox-runtimeで入れるよう案内しています。一方、sandbox-runtimeを入れていないネイティブ版でも失敗は出たと、8月18日のコメントは報告しています。npmパッケージを外しても、この不具合の逃げ道にはなりません。
似た症状の別原因と混同しない
npmでインストールした環境では、apply-seccompバイナリ自体に実行権限が付いていないケースが報告されています。macOSのHomebrew経由のnpmインストールでも、同じ手順を挙げるコメントがあります。
sudo chmod +x /usr/local/lib/node_modules/@anthropic-ai/claude-code/vendor/seccomp/*/apply-seccompただし、この実行権限の欠落は今回のCAP_SYS_ADMINエラーの原因ではないと、同じIssueの別のコメントが指摘しています。ネイティブインストールでは権限の問題が起きず、ヘルパーは起動したうえで拒否されるためです。
socatをアンインストールすると症状が消えたという報告もあります。これは前節のとおりサンドボックスを無効化しているだけで、修正ではありません。
Bubblewrapを非特権コンテナの中で動かすと、bwrap: Can't mount proc on /newroot/proc: Operation not permittedという別のエラーで失敗することもあります。公式ドキュメントのTroubleshootingが扱う制限で、enableWeakerNestedSandboxをtrueにすると、コンテナが用意した/procをそのままバインドマウントして回避します。メッセージが「Operation not permitted」で、かつコンテナの中で出ているなら、本記事の対処では直りません。
公式のAppArmorプロファイルは効くのか
公式のサンドボックスドキュメントは、Ubuntu 24.04以降の制限に対して、bwrapだけにユーザー名前空間の作成を許可するプロファイルを示しています。まず制限の有無を確認します。
sysctl kernel.apparmor_restrict_unprivileged_userns値が1なら制限が有効です。0のとき、またはキーがない旨のエラーが出たときは、この手順は不要です。値が1のときは、次のプロファイルを追加してAppArmorを再読み込みします。
sudo tee /etc/apparmor.d/bwrap > /dev/null <<'EOF'
abi <abi/4.0>,
include <tunables/global>
profile bwrap /usr/bin/bwrap flags=(unconfined) {
userns,
include if exists <local/bwrap>
}
EOF
sudo systemctl reload apparmorこのプロファイルは/usr/bin/bwrapにだけ適用され、サンドボックス内部のコマンドには効きません。Issueでの評価は割れています。7月16日のコメントは、この手順をやり直して直ったと報告しました。8月18日のコメントは、公式のプロファイルがbubblewrapだけを対象にしているため、このエラーには足りない場合があると書いています。5月15日のコメントは、denyはallowやlocal/の上書きより常に優先されるので、配布元のbwrap-userns-restrictにある拒否行は上書きできないと述べています。
回避策と、それぞれが手放すもの
{
"sandbox": {
"enabled": true,
"allowUnsandboxedCommands": false,
"network": { "allowAllUnixSockets": true }
}
}| 対策 | 内容 | 手放すもの |
|---|---|---|
network.allowAllUnixSockets: true | 内容seccompフィルターを使わずにサンドボックスを起動する | 手放すものUnixソケットの遮断(ファイルシステムの隔離は残る) |
bwrap-userns-restrictを直接編集 | 内容audit deny capabilityをコメントアウトしallow capability sys_adminを追加 | 手放すものFlatpakなどすべての非特権bwrapアプリにCAP_SYS_ADMINを再付与する |
| 干渉する別プロファイルの確認 | 内容Lutrisが導入する/etc/apparmor.d/usr.bin.lutrisなどがunpriv_bwrapを上書きしていないか見る | 手放すもの該当する環境だけの対処 |
sandbox.enabled: false | 内容サンドボックスそのものを無効化する | 手放すものファイルシステムとネットワークの隔離が丸ごと失われる |
| v2.1.91への固定 | 内容自動更新を止めて古いバージョンに留める | 手放すもの将来socatを入れた時点で同じ制限にぶつかる可能性がある |
一番上の行が、サンドボックスを残せる回避策です。公式の設定リファレンスでは、LinuxとWSL2のseccompフィルターがsocket(AF_UNIX, ...)の呼び出しを遮断しており、allowAllUnixSocketsがそれを許可する唯一の手段だと説明されています。macOS向けのallowUnixSocketsのパス一覧はLinuxでは無視されます。
4月21日のコメントから、allowAllUnixSockets: trueで直ったという報告が複数出ています。8月18日のコメントは2.1.234で測り、この設定だけで、setgroupsはdenyの非初期ユーザー名前空間のまま、ワークスペース外への書き込みは拒否され、cwd内は書き込めたと報告しました。sandbox.enabled: falseに逃げるよりずっと小さな代償です。
ここでallowUnsandboxedCommandsも確認しておきます。この値が既定のtrueのままだと、最初のコマンドが失敗したあと、モデルがdangerouslyDisableSandboxで再試行し、サンドボックスの外で実行される経路が残ります。8月18日のコメントはこの挙動を観測しています。falseにすると、この再試行は無視されます。
個別のコマンドだけをサンドボックス対象外にするsandbox.excludedCommandsでdockerなど非対応コマンドを対象外にするという設定もあります。ただし、この不具合はサンドボックスの起動自体で起きるため、特定コマンドを除外しても他のコマンドで同じエラーに当たります。
修正はまだ入っていない
Issueはopenのままで、最後のコメントは8月24日、コメントは28件です。8月18日のコメントは、これを再現済みの回帰として開いたままにすると書いています。同じコメントは暫定策にkernel.apparmor_restrict_unprivileged_userns=0を挙げ、Troubleshootingを案内しています。ただし同じ日の11:21のコメントは、これに反論しています。6月の測定(7.0.0-15)でも、#81799(7.0.0-28、sysctlは両方0でAppArmorはunconfined)でも直らなかったためです。8月24日のコメントは、2.1.224・2.1.226・2.1.231の3バージョンで同じ失敗が出たと報告しています。CHANGELOGにこの不具合の修正を示す記載は、v2.1.289まで載っていません。
8月5日のコメントは修正案として、/proc/self/setgroupsがすでにdenyなら書き込みを飛ばす、という変更を挙げました。実現すればallowAllUnixSocketsなしで解消する見込みです。他のAIコーディングエージェントがLinux上で分離をどう作っているかはAIコーディングエージェントのサンドボックス実装比較で比較しています。
まとめ
エラー文は「CAP_SYS_ADMINが足りない」と言いますが、Issueの検証ではbwrapのsetgroups=denyの継承説のほうが、sysctlを0にしても直らない事実と合います。Ubuntuで試せる手段は、公式のAppArmorプロファイルと、Unixソケットの遮断だけを手放すallowAllUnixSockets: trueの2つです。8月24日のコメントは、単一段のbwrap(--unshare-user --cap-drop ALL)は通り、入れ子のときだけ失敗すると書いています。AppArmor側の原因を切り離せる根拠です。unpriv_bwrapの編集やsandbox.enabled: falseは、手放すものが大きい側にあります。
参照した一次ソース
この記事の記述は、次の一次ソースと照合しています。更新時に参照先が変わった場合は一覧も更新します。