1
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Claude Code の settings.json 全文公開。サンドボックス+auto モードで確認を最小にする設定【コピペ用】

1
Last updated at Posted at 2026-08-02

2026年8月に追記しました。運用を続けるうちに、自分の設定に抜け道が1つ残っていたことに気づいたので、その1行と、バージョンごとの挙動差を足しています。追記箇所は「1か月運用して、足りなかった1行」と「バージョンで変わったところ」の2節です。JSON 本体は当時のまま載せています。

Claude Code の確認プロンプトを減らしつつ、危ない操作は通らないようにする設定です。運用していて、確認は格段に減り、確認疲れによるミスも減りました。

settings.json の全文と、PreToolUse フックのスクリプトを載せます。ユーザー名など環境依存の部分は伏せてありますが、それ以外はそのまま動く形です。上から読む必要はないので、必要なところをコピーして持って帰ってください。

検証環境:【Claude Code のバージョン、macOS のバージョン、確認日を入れる】

土台になっているのは3行です。

"defaultMode": "auto",                  // 日常の確認を出さない
"autoAllowBashIfSandboxed": true,       // サンドボックス内なら Bash も確認なし
"failIfUnavailable": true               // サンドボックスが使えないなら実行しない

3行目が無いと、サンドボックスが黙って外れた状態で自動実行が続きます。1行目と3行目はセットです。

1か月運用して、足りなかった1行

先に、今回の追記のいちばん大事なところを書きます。下の JSON には、抜け道が1つ残っていました。

"allowUnsandboxedCommands": false

これは既定で true です。true のあいだは、サンドボックス内で失敗したコマンドを、サンドボックスなしで再実行する経路が生きています。dangerouslyDisableSandbox という脱出ハッチです。

自分は記事の中で「deny は、その制限を迂回できる汎用の抜け道から塞ぐ」と書きました。wp eval を塞ぐ理由と、まったく同じ話です。それなのに、サンドボックス側の脱出ハッチには手をつけていませんでした。failIfUnavailable でサンドボックスが起動しない場合は止められるのに、起動したあとで外に出る経路のほうは開いていた。

excludedCommands に入れた docker git gh は、この設定を false にしても従来どおりサンドボックス外で動きます。止まるのは、それ以外のコマンドが「サンドボックスで失敗したから外でやり直す」という動きだけです。

もう1つ、サンドボックスの読み取り側についても書いておきます。既定の読み取りポリシーは、認証情報を露出させたままです。だから credentials.files~/.ssh~/.aws を明示的に書く必要がある。書かなければ読めてしまう、という前提で組まれています。

さらに絞るなら、ホームディレクトリ全体を読めなくして、作業ディレクトリだけ開ける書き方があります。

"filesystem": {
  "denyRead": ["~/"],
  "allowRead": ["."]
}

自分はまだこれを入れていません。ホーム直下の設定ファイルを読ませたい場面が読み切れていないからです。入れるなら、日常の作業が止まらないかを1週間くらい見てからにするつもりです。

settings.json 全文

{
  "env": {
    "CLAUDE_CODE_DISABLE_ADAPTIVE_THINKING": "1"
  },
  "permissions": {
    "defaultMode": "auto",
    "disableBypassPermissionsMode": "disable",
    "allow": [
      "Read",
      "Grep",
      "Glob",
      "Edit",

      "WebFetch(domain:developer.wordpress.org)",
      "WebFetch(domain:make.wordpress.org)",
      "WebFetch(domain:core.trac.wordpress.org)",
      "WebFetch(domain:translate.wordpress.org)",
      "WebFetch(domain:code.claude.com)",
      "WebFetch(domain:docs.claude.com)",
      "WebFetch(domain:developer.mozilla.org)",
      "WebFetch(domain:docs.stripe.com)",

      "Bash(cd:*)", "Bash(pwd)", "Bash(ls:*)", "Bash(cat:*)",
      "Bash(head:*)", "Bash(tail:*)", "Bash(wc:*)",
      "Bash(rg:*)", "Bash(grep:*)", "Bash(find:*)", "Bash(jq:*)",
      "Bash(sort:*)", "Bash(uniq:*)", "Bash(cut:*)", "Bash(diff:*)",
      "Bash(sed:*)", "Bash(awk:*)", "Bash(echo:*)", "Bash(printf:*)",
      "Bash(date:*)", "Bash(which:*)", "Bash(basename:*)",
      "Bash(dirname:*)", "Bash(realpath:*)", "Bash(stat:*)",
      "Bash(file:*)", "Bash(tree:*)", "Bash(du:*)",
      "Bash(mkdir:*)", "Bash(cp:*)", "Bash(mv:*)", "Bash(touch:*)",
      "Bash(zip:*)", "Bash(unzip:*)", "Bash(tar -tf:*)",

      "Bash(git status:*)", "Bash(git diff:*)", "Bash(git log:*)",
      "Bash(git show:*)", "Bash(git add:*)", "Bash(git branch:*)",
      "Bash(git fetch:*)", "Bash(git pull:*)", "Bash(git commit:*)",
      "Bash(git push:*)", "Bash(git switch:*)", "Bash(git checkout -b:*)",
      "Bash(git restore --staged:*)", "Bash(git merge:*)",
      "Bash(git rebase:*)", "Bash(git cherry-pick:*)",
      "Bash(git revert:*)", "Bash(git stash:*)", "Bash(git tag:*)",
      "Bash(git blame:*)", "Bash(git reflog:*)", "Bash(git rev-parse:*)",
      "Bash(git ls-files:*)", "Bash(git worktree:*)",
      "Bash(git remote -v)", "Bash(git remote get-url:*)",
      "Bash(git config --get:*)",

      "Bash(gh pr list:*)", "Bash(gh pr view:*)", "Bash(gh pr create:*)",
      "Bash(gh pr checks:*)", "Bash(gh issue list:*)",
      "Bash(gh issue view:*)", "Bash(gh run list:*)",
      "Bash(gh run view:*)", "Bash(gh run watch:*)",
      "Bash(gh repo view:*)", "Bash(gh auth status)",

      "Bash(npm run:*)", "Bash(npm test:*)", "Bash(npm install:*)",
      "Bash(npm ci:*)", "Bash(npm ls:*)", "Bash(npm -v)",
      "Bash(npx wp-scripts:*)", "Bash(node -v)", "Bash(node --version)",

      "Bash(composer install:*)", "Bash(composer validate:*)",
      "Bash(composer dump-autoload:*)", "Bash(composer show:*)",
      "Bash(vendor/bin/phpunit:*)", "Bash(vendor/bin/phpcs:*)",
      "Bash(vendor/bin/phpcbf:*)",
      "Bash(phpunit:*)", "Bash(phpcs:*)", "Bash(phpcbf:*)",
      "Bash(php -l:*)", "Bash(php -v)",

      "Bash(msgfmt:*)", "Bash(msgmerge:*)", "Bash(msgcat:*)",
      "Bash(msgattrib:*)", "Bash(wp i18n:*)",

      "Bash(wp plugin list:*)", "Bash(wp option get:*)",
      "Bash(wp core version:*)", "Bash(wp cli info)"
    ],
    "ask": [
      "Bash(svn commit:*)",
      "Bash(svn ci:*)",
      "Bash(gh release create:*)",
      "Bash(git push --tags:*)"
    ],
    "deny": [
      "Read(**/.env)",
      "Read(**/.env.*)",
      "Read(~/.ssh/**)",
      "Read(~/.aws/**)",
      "Read(~/.gnupg/**)",
      "Read(~/.config/gh/**)",
      "Read(~/.npmrc)",
      "Read(**/*.pem)",
      "Read(**/id_rsa*)",
      "Read(**/id_ed25519*)",

      "Edit(~/.claude/settings.json)",
      "Edit(~/.claude/hooks/**)",
      "Edit(**/.git/hooks/**)",

      "Bash(curl:*)", "Bash(wget:*)", "Bash(nc:*)", "Bash(sudo:*)",

      "Bash(rm -rf /)", "Bash(rm -rf /*)",
      "Bash(rm -rf ~)", "Bash(rm -rf ~*)",

      "Bash(git clean:*)", "Bash(git reset --hard:*)",
      "Bash(git push --force:*)", "Bash(git push -f:*)",
      "Bash(git filter-branch:*)",
      "Bash(git stash drop:*)", "Bash(git stash clear:*)",
      "Bash(git remote set-url:*)",
      "Bash(gh repo delete:*)", "Bash(npm publish:*)",

      "Bash(wp plugin install:*)", "Bash(wp plugin delete:*)",
      "Bash(wp plugin uninstall:*)",
      "Bash(wp db drop:*)", "Bash(wp db reset:*)", "Bash(wp db import:*)",
      "Bash(wp site empty:*)",
      "Bash(wp eval:*)", "Bash(wp eval-file:*)", "Bash(wp shell:*)"
    ]
  },
  "autoMode": {
    "environment": [
      "$defaults",
      "Organization: 一人でやっている WordPress プラグイン開発。主な用途は PHP と JavaScript でのプラグイン開発と、技術ブログの執筆。",
      "Source control: GitHub の個人アカウント。そこに置いたリポジトリは信頼できる。WordPress.org で配布しているものは public、それ以外は private。",
      "Internal package registry: プライベートレジストリは無い。npm は registry.npmjs.org、Composer は repo.packagist.org のみ。それ以外を指すインストールは異常。",
      "Key internal services: リリースに使う WordPress.org のプラグインディレクトリと plugins.svn.wordpress.org、CI に使う GitHub Actions。",
      "Sensitive remote targets: 本番サイトとその WordPress データベース、および WordPress.org の SVN trunk と tags。SVN へのコミットは既存の全ユーザーにリリースを配信し、取り消せない。デプロイやリリースは、それを名指しした明示的な指示があるときだけ。",
      "Sensitive data locations: Stripe の API キー、Pro 版のライセンスと顧客データ、.env と wp-config.php。いずれもこのマシンから出さない、git リポジトリに入れない。",
      "Additional context: ステージング環境は無い。作業コピーはローカルにあり、その中の一部(作業メモ、ドキュメント)は意図的に git 管理外なので、削除すると git から戻せない。ファイル削除と履歴の書き換えは影響が大きいものとして扱う。",
      "日常のローカル作業は信頼してよい。コミット、ブランチ操作、マージ、ローカルブランチのリベース、ビルド、テスト、リンター、i18n ツールの実行、自分の GitHub リポジトリへの push は通常業務であり、確認は不要。"
    ],
    "soft_deny": [
      "$defaults",
      "git 管理外のファイルを削除・移動しない。node_modules / vendor / dist のようなビルド生成物以外のディレクトリを削除しない。代わりに確認すること。",
      "WordPress コア(wp-admin/, wp-includes/, wp-settings.php)と、他人のプラグイン・テーマのディレクトリを編集しない。自分のプラグインディレクトリの中だけで作業すること。",
      "動作中の WordPress サイトのデータベースに書き込まない(ローカルサイトを含む)。その変更を明示的に依頼された場合を除く。"
    ],
    "hard_deny": [
      "$defaults",
      "Claude Code 自身の設定とガードレールを変更しない: ~/.claude/settings.json, ~/.claude/hooks/, リポジトリの .claude/ ディレクトリ, git hooks。"
    ]
  },
  "sandbox": {
    "enabled": true,
    "autoAllowBashIfSandboxed": true,
    "failIfUnavailable": true,
    "excludedCommands": ["docker", "git", "gh"],
    "network": {
      "strictAllowlist": true,
      "allowedDomains": [
        "registry.npmjs.org", "*.npmjs.org", "*.npmjs.com",
        "registry.yarnpkg.com",
        "nodejs.org", "*.nodejs.org",
        "packagist.org", "*.packagist.org", "getcomposer.org",
        "wordpress.org", "*.wordpress.org",
        "github.com", "*.github.com", "codeload.github.com",
        "raw.githubusercontent.com", "objects.githubusercontent.com"
      ]
    },
    "filesystem": {
      "allowWrite": [
        "~/.npm", "~/.composer",
        "~/Library/Caches/composer", "~/.cache"
      ]
    },
    "credentials": {
      "files": [
        { "path": "~/.ssh",             "mode": "deny" },
        { "path": "~/.aws",             "mode": "deny" },
        { "path": "~/.gnupg",           "mode": "deny" },
        { "path": "~/.config/gh",       "mode": "deny" },
        { "path": "~/.npmrc",           "mode": "deny" },
        { "path": "~/.subversion/auth", "mode": "deny" }
      ],
      "envVars": [
        { "name": "GITHUB_TOKEN",          "mode": "deny" },
        { "name": "GH_TOKEN",              "mode": "deny" },
        { "name": "NPM_TOKEN",             "mode": "deny" },
        { "name": "STRIPE_SECRET_KEY",     "mode": "deny" },
        { "name": "STRIPE_API_KEY",        "mode": "deny" },
        { "name": "AWS_ACCESS_KEY_ID",     "mode": "deny" },
        { "name": "AWS_SECRET_ACCESS_KEY", "mode": "deny" }
      ]
    }
  },
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "bash ~/.claude/hooks/protect-plugin-dirs.sh"
          }
        ]
      }
    ]
  },
  "alwaysThinkingEnabled": true,
  "tui": "fullscreen",
  "theme": "dark"
}

以下、判断が入っている箇所だけ補足します。

permissions:allow の考え方

allow は「読む・探す・変換する・テストする」までにしています。cat grep find sed awk jqgit status git diffnpm test phpunit phpcs。ここに確認を出しても、読まずに通すだけです。

そのうえで、外に出す経路だけ塞いでいます。

"Bash(curl:*)", "Bash(wget:*)", "Bash(nc:*)"

sed でファイルを加工することは許して、curl で送ることは許さない。読む権限と、持ち出す経路を分けて考えます。

Bash(tar -tf:*) だけを許可しているのも同じ発想です。-t は中身を一覧するだけなので安全ですが、-x は展開してファイルを書きます。サブコマンド単位で切れるところは切ります。

permissions:ask を4つに絞る

"ask": [
  "Bash(svn commit:*)",
  "Bash(svn ci:*)",
  "Bash(gh release create:*)",
  "Bash(git push --tags:*)"
]

確認を出すのは、外に公開されて取り消せない操作だけです。WordPress.org の SVN にコミットすると、その瞬間に既存の全ユーザーへリリースが配信されます。取り消せません。自分にとっていちばん影響が大きい操作がこれなので、ここだけは必ず止まるようにしています。

**数を絞ることが目的です。**確認が4つしかないので、出たときに読みます。数が多いと、確認は信号ではなくノイズになります。

permissions:deny で先に塞ぐべきもの

deny のリストで、最初に入れるべきだと思っているのがこれです。

"Bash(wp eval:*)",
"Bash(wp eval-file:*)",
"Bash(wp shell:*)"

wp eval は任意の PHP を実行します。つまり wp db drop を deny にしても、wp eval が通れば同じことができます。**汎用の抜け道を塞がないと、個別の deny は意味を持ちません。**冒頭に書いた allowUnsandboxedCommands の話と、構造は同じです。

同じ理由で、設定自体の編集も塞いでいます。ガードレールを守るガードレールです。

"Edit(~/.claude/settings.json)",
"Edit(~/.claude/hooks/**)",
"Edit(**/.git/hooks/**)"

git 系で deny にしているものは、履歴か未追跡ファイルが消えるものに絞っています。git clean は未追跡ファイルが消え、git reset --hard は変更が消え、git push --force はリモートの履歴が消え、git stash drop は stash が消え、git filter-branch は履歴が書き換わる。

git commit や force なしの git push は allow です。ここを止めると日常が回らなくなります。止めるのは、戻せないものだけ。

sandbox:3行の組み合わせ

autoAllowBashIfSandboxed が確認削減の本体で、failIfUnavailable がその安全弁です。後者を false にすると、サンドボックスが使えないときにサンドボックスなしで自動実行されます。いちばん危ない状態なので、必ず true にします。

excludedCommands は妥協です。git と gh は認証情報と外部通信を使うので、サンドボックス内だと素直に動きません。無理に入れると、結局サンドボックス自体を切ることになります。なので3つは外に出して、permissions とフックで縛る形にしました。1つの層で全部を守ろうとしない、という割り切りです。

ネットワークは strictAllowlist で固定しています。プライベートレジストリが無いので、公開レジストリ以外を指すインストールは異常です。ここは環境によって変わるので、自分の依存の取得先に合わせて書き換えてください。

認証情報では ~/.subversion/auth を deny に入れています。WordPress.org の配布が SVN なので、ここが読めるとリリースが打てます。.ssh.aws と並べて、最初に塞ぐべき場所でした。

バージョンで変わったところ

ここも追記です。設定の意味そのものが変わった箇所があります。

failIfUnavailable は v2.1.83 で入った比較的新しいキーです。それより前のバージョンでは、サンドボックスが起動できないときに警告だけ出して、そのまま素通しで実行されます。古いバージョンのまま「サンドボックスを有効にした」と思っている状態が、いちばん危ない。

もう1つ。v2.1.139 より前は、シェル展開を含むコマンドがサンドボックス自動承認の対象から外れていました。$VAR$(cmd) を含むだけで確認に落ちていたということです。いまは正しく認識されるので、**確認が減らないと感じていた人は、まずバージョンを見てください。**設定の問題ではないかもしれません。

なお、このサンドボックスは Windows のネイティブ環境では動きません。WSL2 かコンテナの中で動かす必要があります。

PreToolUse フック(全文)

~/.claude/hooks/protect-plugin-dirs.sh に置いて、実行権限を付けます。

#!/usr/bin/env bash
#
# protect-plugin-dirs.sh — PreToolUse(Bash) guard.
#
# プラグイン開発フォルダ(prime-cache / prime-cache-pro)の削除・移動・上書きと、
# 作業ツリーを吹き飛ばす類のコマンドをブロックする。
# 2026-07-19 のフォルダ消失を受けて追加。
#
# PreToolUse の JSON を標準入力から読み、危険なら deny を出力する。
# それ以外はすべて exit 0(許可)。パースに失敗した場合も許可する(fail-open)ので、
# このガードのバグでセッションが止まることはない。

input=$(cat)

# jq が無い / command が無い → 見るものがないので許可
command -v jq >/dev/null 2>&1 || exit 0
cmd=$(printf '%s' "$input" | jq -r '.tool_input.command // empty' 2>/dev/null)
[ -z "$cmd" ] && exit 0

low=$(printf '%s' "$cmd" | tr '[:upper:]' '[:lower:]')

deny() {
  reason=$(printf '%s' "$1" | jq -R -s .)
  printf '{"hookSpecificOutput":{"hookEventName":"PreToolUse","permissionDecision":"deny","permissionDecisionReason":%s}}\n' "$reason"
  exit 0
}

# 1) 壊滅的な削除。/, ~, $HOME, カレントディレクトリ, 裸のグロブを対象にした rm -rf。
#    カレントディレクトリ自体がプラグインフォルダなので "." を含めている。
if printf '%s' "$low" | grep -Eq 'rm[[:space:]]+(-[a-z]*[rf][a-z]*[[:space:]]+)+(/|~|\$home|\.|\*)([[:space:]]|/|$)'; then
  deny "Blocked: /, ~, カレントディレクトリ, 裸のグロブへの再帰削除。作業ツリーが消える経路です。本当に必要ならターミナルで自分で実行してください。"
fi

# 2) プラグイン開発フォルダを終端のパスセグメントとして名指しする破壊的操作。
#    末尾は「スラッシュ・空白・行末」に限定しているので、prime-cache.zip は
#    マッチしない(リリースビルドの rm -f prime-cache.zip は通る)。
target='(^|[/[:space:]"'"'"'])(prime-cache|prime-cache-pro)/?([[:space:]"'"'"']|$)'
destructive='rm[[:space:]]+-[a-z]*r|(^|[[:space:]])rmdir[[:space:]]|(^|[[:space:]])mv[[:space:]]|(^|[[:space:]])trash[[:space:]]|-delete([[:space:]]|$)|-exec[[:space:]]+rm|rsync[[:space:]].*--delete|git[[:space:]]+clean'
if printf '%s' "$low" | grep -Eq "$destructive"; then
  if printf '%s' "$low" | grep -Eq "$target"; then
    deny "Blocked: プラグイン開発フォルダ(prime-cache / prime-cache-pro)を削除・移動・上書きする可能性があります。一度失っているので止めています。本当に必要なら Claude の外で実行してください。"
  fi
fi

# 3) フォルダごと置き換わる install / delete 系
if printf '%s' "$low" | grep -Eq 'wp[[:space:]]+plugin[[:space:]]+(install|delete|uninstall)'; then
  deny "Blocked: 'wp plugin install/delete' は開発フォルダを上書き・削除しえます。Claude からは実行しません。"
fi
if printf '%s' "$low" | grep -Eq 'git[[:space:]]+clean'; then
  deny "Blocked: 'git clean' は未追跡ファイルを消します。ローカルにしかないドキュメントが消えるので、必要なら手動で。"
fi

exit 0

このスクリプトで気をつけたのは3点です。

**fail-open にしています。**jq が無くても、JSON が壊れていても許可します。ガードのバグでセッション全体が止まると、たぶんガードごと外すことになるからです。外側にサンドボックスと permissions があるので、この層は安全側に倒しすぎない、という判断でした。

**rm -rf .. を対象に入れています。**作業中のディレクトリ自体がプラグインフォルダなので、. の削除がそのままフォルダ消失になります。

**リリースビルドを誤爆させません。**パターンの末尾を「スラッシュ・空白・行末」に限定しているので、prime-cache/ はマッチし、prime-cache.zip はマッチしません。ビルド時の rm -f prime-cache.zip は通ります。止まりすぎるガードは、外されます。

mv を破壊的操作に含めているのも要点です。移動も、元の場所からは消えます。rsync --deletefind -delete も忘れやすい経路なので入れてあります。

$defaults の落とし穴

auto モードのルールを自分で書くときの注意です。知らないと、静かに無防備になります。

$defaults は値ではなく、組み込みルールをその位置に展開するマーカーです。

"soft_deny": ["$defaults", "自分のルール1", "自分のルール2"]

ここで重要なのは、「配列を書かない」と「配列を書いたが $defaults が無い」がまったく別の挙動だということです。4つのセクションは独立に評価されるので、environment だけ書けば残り3つは組み込みのまま維持されます。ところが、配列を明示的に書いて $defaults を入れ忘れると、そのセクションの組み込みルールは全部捨てられます。

とくに怖いのが soft_denyhard_deny です。$defaults の無い soft_deny は、git push --forcecurl | bash の組み込みブロックを全部消します。hard_deny なら、組み込みのデータ持ち出し防止と auto モード迂回防止が消えます。

自分で3行書いたつもりが、実際には「その3行以外は全部素通し」になっている。設定は増えているように見えるので、見た目では気づけません。

保存したら、展開後を確認します。

# $defaults 展開後の、分類器が実際に使う実効ルールを JSON で表示
claude auto-mode config

# 組み込みルールだけを表示
claude auto-mode defaults

# ラベルの先頭一致で1件だけ読む
claude auto-mode defaults --label 'Git Destructive'

# 自作ルールの曖昧さ・重複・誤検知しそうな箇所を指摘してもらう
claude auto-mode critique

claude auto-mode config で展開後を見れば、組み込みが消えているかは一目で分かります。設定を書いたときではなく、展開後を見る。

組み込みルールを足すのではなく書き換えたい場合は、claude auto-mode defaults の出力をファイルに保存し、リストを編集してから貼り戻すのが正攻法です。

導入する順番

全部いっぺんに入れなくても大丈夫です。効く順に並べるとこうなります。

1. サンドボックスの3行。enabled / autoAllowBashIfSandboxed / failIfUnavailable。ここだけで、確認の量と安全性の両方が変わります。

2. 脱出ハッチを閉じる。allowUnsandboxedCommands: false。今回追記した1行です。1番だけ入れて2番を飛ばすと、外に出る経路が残ります。

3. deny の抜け道。wp eval 系、設定ファイルの編集、curl wget nc。個別の危険操作より先にここを塞ぎます。

**4. ask を絞る。**取り消せない操作だけ。多いと読まなくなります。

**5. allow を広げる。**読む・探す・テストするものを入れて、日常が止まらない状態にします。ここが狭いと、結局 auto モードの意味が薄れます。

6. $defaults の確認。claude auto-mode config を1回打つ。既に auto モードのルールを書いている人は、いますぐ打ってください。

**7. フック。**permissions で表現できないものが出てきてから書けば十分です。自分は事故が起きてから書きました。

まとめ

  • defaultMode: auto は、確認以外で止まる仕組みとセットで入れる
  • autoAllowBashIfSandboxedfailIfUnavailable は必ず両方 true
  • allowUnsandboxedCommands は既定 true。サンドボックスの外に出る経路が残るので false にする
  • deny は「その制限を迂回できる汎用の抜け道」(wp eval / wp shell / 設定ファイルの編集)から塞ぐ
  • 読む権限(sed awk grep)と持ち出す経路(curl wget nc)を分ける
  • ask は取り消せない操作だけ。絞るほど、出たときに読む
  • git の deny は「戻せないもの」に限定。commit / push を止めると日常が回らない
  • 認証情報は ~/.ssh だけでなく、自分の配布経路(SVN なら ~/.subversion/auth)も塞ぐ
  • サンドボックスの既定の読み取りポリシーは認証情報を露出させる。credentials.files に明示的に書く
  • フックは fail-open でよい。外側に層があるなら、内側は止まりすぎないほうが続く
  • ガードのパターンは誤爆させない。prime-cache/ は止めて prime-cache.zip は通す
  • $defaults を書き忘れたセクションは組み込みが全消え。claude auto-mode config で展開後を必ず確認

確認の数を増やすより、確認が出たときに必ず読む状態を作るほうが効きました。

そのうえで今回、自分の設定に1つ抜け道が残っていたことに気づきました。抜け道を塞ぐ、と書いた本人が、別の層の抜け道を見落としていたわけです。あなたの設定に、まだ開いている経路はありませんか。


ふだんはraplsworks.comで、WordPressプラグイン開発やClaude Codeまわりのことを書いています。

1
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?