# Claude Codeを本番運用に耐えさせる — 権限設計・hooks・CLAUDE.md・セキュリティゲート

> Claude Codeを本番運用に耐えさせる設定を実装者視点で解説。permissionのdenyで秘密情報をfail-closedに閉じ、hooksでスキャンを自動発火させ、CLAUDE.mdで規約を固定する。設定では閉じない認可/IDOR・RLSの縦リスクはaegis fixのループと設計で塞ぐ役割分担を示します。

- 公開日: 2026-07-07
- 著者: 友田 陽大
- タグ: Claude Code, AI駆動開発, バイブコーディング, セキュリティ, Supabase, RLS
- URL: https://tomodahinata.com/blog/claude-code-production-operations-security-gates-guide
- カテゴリ: バイブコーディング
- 総合ガイド: https://tomodahinata.com/blog/vibe-coding-what-is-tools-risks-production-guide

## 要点

- Claude Codeを本番運用に耐えさせるのは、プロンプトの巧拙ではなく『設定』——permission・hooks・CLAUDE.md を先に固めること
- permission は deny を先に書く。秘密情報（.env / secrets）とネットワーク発信を fail-closed に閉じ、最小権限でエージェントを走らせる
- CLAUDE.md の規約は『助言』、hooks は『決定的』。決定的に守りたい統制は hooks で scan を自動発火させ、Stop フックで検証を通るまでターンを止める
- permission・hooks・CLAUDE.md は水平の統制を自動化するが、認可/IDOR・RLS設計という縦のリスクは設定では閉じない——`aegis fix --format json` で機械可読な修正計画を渡し、縦は設計で塞ぐ
- 役割分担：Spec駆動（何を作るか）→ Claude Code設定（ローカルループの安全）→ CIゲート（最後の砦）→ 縦のリスクは設計レビュー/監査

---

最初に結論を述べます。**Claude Codeを本番運用に耐えさせる鍵は、エージェントの「賢さ」でも、プロンプトの巧拙でもありません。エージェントを走らせる『環境の設定』——permission（権限）・hooks・CLAUDE.md・検証ゲート——を先に固めることです。** 同じモデル・同じプロンプトでも、`settings.json` と `CLAUDE.md` の設計次第で、出力が本番に出てよいコードになるか、事故を待つコードになるかが変わります。私が一人 × Claude Code で経済産業大臣賞を受賞したB2B SaaSや本番二重課金0件の決済基盤、放送局向けAI基盤を作ってこられたのは、生成の速さそのものではなく、この「設定を先に固める」規律に負うところが大きい。

本記事は、**Claude Code本体をどう設定すれば、生成の速度をそのまま出荷の速度にできるか**を、実装者の視点で具体的に書きます。方法論（何を作るか）や、CIでの機械的合否（最後の砦）は既存記事に譲り、ここは**その手前——ローカルのエージェントループそのものを安全にする層**に絞ります。

---

## 1. 本番運用の分岐点は「プロンプト」ではなく「設定」

AIコーディングの議論はプロンプトに集中しがちですが、本番運用で効くのはその外側です。私は開発を3つの層に分けて設計しています。役割が違うので、混ぜてはいけません。

| 層 | 何を決めるか | 主な道具 | 詳説 |
|---|---|---|---|
| **① 方法論** | 何を作るか（仕様を握る） | 探索→計画→実装→検証 | [Spec駆動開発の本番ワークフロー](/blog/spec-driven-development-claude-code-ai-agent-production-workflow) |
| **② エージェント設定**（本記事） | ローカルループを安全にする | permission・hooks・CLAUDE.md | この記事 |
| **③ CIゲート** | 最後の砦（機械的合否・リモート） | 型・テスト・静的解析・セキュリティ | [AI駆動開発の品質ゲート](/blog/ai-driven-development-quality-gates-ci-type-safety-test-security) |

①は「AIに実装させるが、仕様の決定はさせない」という方法論の話。③は「AIの出力が本番に出てよいかを、主観ではなく合否で判定する」CIの話。本記事の②は、その2つの間にある**Claude Code本体の設定**です。ここが緩いと、①で立てた仕様も③のCIも、手前のローカルループで無限に手戻りを生みます。逆にここを固めれば、Claudeが編集した瞬間にセキュリティスキャンが走り、秘密情報には触れさせず、規約から外れた実装はその場で止まる——生成の速度を落とさずに、事故だけを削れます。

以降、②を構成する **permission → hooks → CLAUDE.md → 縦のリスクの扱い** の順に、実際の `settings.json` を交えて掘ります。

---

## 2. 権限設計：deny を先に書く（fail-closed な allowlist）

Claude Codeの権限は `settings.json` の `permissions` で `allow` / `ask` / `deny` の3配列で表現します。ここで最初にやるべきは、**便利にする `allow` ではなく、閉じる `deny` を先に書く**ことです。セキュリティの原則は fail-closed——曖昧なら安全側に倒す——だからです。

```json
{
  "permissions": {
    "deny": [
      "Read(./.env)",
      "Read(./.env.*)",
      "Read(./secrets/**)",
      "Bash(curl *)"
    ],
    "allow": [
      "Bash(npm run lint)",
      "Bash(npm run test *)",
      "Bash(npx @aegiskit/cli scan)"
    ]
  }
}
```

この `deny` が守っているのは、**秘密情報とネットワーク発信**という、AIエージェントに触らせて事故になりやすい2点です。私の実際の設定では、`~/.claude/settings.json` が `.env*`・`*.pem`・`*.key`・`.aws/**`・`.ssh/**`・`credentials*` の読み取りを一律に拒否しています。これはただの用心ではありません。Supabaseの `service_role` キーは PostgreSQL の `BYPASSRLS` 権限で動き、**RLSを完全に無視します**。つまり本番の守りの境界は、コードのロジックではなく「鍵がどこに置かれ、誰が読めるか」に移る。だからエージェントに秘密情報を読ませない `deny` を、最初の1行として書くのです。

権限のスコープには明確な優先順位があります（強い順）。

```text
Managed（組織管理） > コマンドライン引数 > Local（.claude/settings.local.json）
  > Project（.claude/settings.json） > User（~/.claude/settings.json）
```

チームで共有する規則は Project の `settings.json`（gitにcommit）に、個人の一時的な緩和は Local（gitignore）に置く。この分離を守ると、「誰かのローカル都合の緩和」が全員に漏れる事故が防げます。

さらに、フェーズごとに権限モードを使い分けます。

- **探索は plan mode**——コードと制約を「読むだけ」で、ファイルは書かせない。仕様を理解させる段階で勝手に実装させないための壁です。
- **非対話バッチは `--allowedTools` で絞る**——`claude -p "..." --allowedTools "Edit,Bash(git commit *)"` のように、無人で走るときほど使えるツールを最小に固定する。
- **auto mode**——分類器モデルが権限の逸脱や未知のインフラ操作だけをブロックし、ルーティンは止めない。方向性は信頼するが逐一の承認は省きたい作業に向きます。

要は、**必要な権限を、必要なフェーズだけ、最小限**。これは人間のIAM設計とまったく同じ規律です。

---

## 3. hooks：scan を「祈り」ではなく「発火」にする

ここがClaude Code固有の、最も効く設定です。**CLAUDE.mdに書いた規約は本質的に「助言（advisory）」ですが、hooks は「決定的（deterministic）」で、必ず実行される**——公式ドキュメントもこの差を明言しています。「編集したら必ずスキャンを回してね」とCLAUDE.mdに書いても、忙しいセッションでは飛ばされます。hooksにすれば、飛ばせません。

Claude Codeのhooksは、ワークフローの特定イベント（`PreToolUse` / `PostToolUse` / `Stop` / `SessionStart` など）で、`settings.json` に書いたコマンドを自動実行します。セキュリティ運用で私が敷くのは、次の2枚です。

```json
{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          { "type": "command", "command": "npx @aegiskit/cli scan" }
        ]
      }
    ],
    "Stop": [
      {
        "hooks": [
          { "type": "command", "command": "npm run verify" }
        ]
      }
    ]
  }
}
```

- **`PostToolUse`（matcher: `Edit|Write`）** — Claudeがファイルを編集・作成した**直後に**、`npx @aegiskit/cli scan` を発火させます。生成したコードにインジェクションの経路や秘密情報の混入、統制の欠落があれば、その場で source→sink のトレース付きで返る。人間が気づくのを待たず、ループの内側で検出が回ります。
- **`Stop`（ターン終了フック）** — Claudeが「終わった」と判断してターンを閉じる前に、検証コマンドを走らせ、**通るまでターンを止めます**。Stopフックは検証がパスするまで終了をブロックできる仕組みで（ただしClaude Codeは8回連続でブロックされるとフックを上書きしてターンを終える——無限ゲートではない点は正直に）、ここに私は `npm run verify`（lint + test + build + scan を束ねた自分のゲート）を置いています。

この2枚が効くのは、**ローカルのエージェントループの「内側」に検証を差し込む**からです。CIの品質ゲート（[AI駆動開発の品質ゲート](/blog/ai-driven-development-quality-gates-ci-type-safety-test-security)）が全員のpushに効く「遠い最後の砦」だとすれば、hooksはClaudeが書いた瞬間に発火する「近い砦」。近い砦は速いフィードバックで手戻りを減らし、遠い砦は取りこぼしを最終的に止める。役割が違うので、どちらか片方ではなく両方を敷きます。CIには同じ検出を `aegis ci`（SARIFをGitHub code scanningへ上げ、高信頼の検出だけがビルドを止めるラッパー）で二重化しておくと、ローカルで無視しても最後に必ず引っかかります。

> **設計思想**: 守りたい統制は「口頭で祈る」のではなく「発火させる」。CLAUDE.mdに書いて守られなかったルールは、hookに変換するサインです。公式も「Claudeが指示なしで正しくやることは消し、決定的に守りたいものは hook にせよ」と言っています。

---

## 4. CLAUDE.md：規約を「会話」ではなく「ファイル」に固定する

hooksが「決定的に強制するもの」なら、CLAUDE.mdは「毎回読ませる助言」です。Claude Codeは**会話の冒頭で必ず CLAUDE.md を読み込む**ため、ここに規約を固定すれば、会話に埋もれて消えることがなくなります。[Spec駆動開発](/blog/spec-driven-development-claude-code-ai-agent-production-workflow)で述べた「仕様・規約をファイル化する」思想の、Claude Code側の実装がこれです（詳細はそちらに譲ります）。

配置には階層があります。私のこのポートフォリオ・リポジトリ自体が、その運用の実例です。

```text
~/.claude/CLAUDE.md        全セッション共通の普遍原則（コード品質の10本柱・秘密情報の扱い）
./CLAUDE.md                リポジトリの憲法（スタック・ルート規約・アンチパターン）
./app/api/CLAUDE.md        ルートハンドラのローカル規約（Zod検証・秘密情報の境界）
./lib/CLAUDE.md            データ層の規約（I/Oの隔離・フレームワーク非依存）
```

ルートに「憲法」を1枚、ディレクトリごとに「ローカル規約」を置き、Claudeはそのファイルを触る前に該当規約を読む。モノレポや大規模リポジトリでも、文脈が汚れずに規約が効きます。CLAUDE.mdに書くべきは、セキュリティ面ではこのあたりです。

- 外部入力は境界で必ず Zod 検証する（`app/api/*` の正規パターンを指す）
- 秘密情報は env / secrets manager のみ。ハードコード禁止
- Supabase RLS は所有者スコープ（`USING (auth.uid() = user_id)`）を既定にし、`USING (true)` は**そのテーブルが本当に公開前提のときだけ**
- `service_role` はブラウザから到達しうる経路で使わない

ただし——**CLAUDE.mdは長くすると無視されます**。公式が繰り返し警告している通り、肥大したCLAUDE.mdは肝心のルールをノイズに埋もれさせます。各行に「これを消したらClaudeが間違えるか？」を問い、Noなら消す。そして「決定的に守りたい」ものはCLAUDE.mdに書き続けるのではなく、**hookに昇格させる**。CLAUDE.md（助言）→ hooks（決定的）→ CI（機械的合否）という強度の段階を、規約ごとに正しく選ぶのが肝心です。「`any` 禁止」のような機械判定できるルールは、CLAUDE.mdに祈らせるより `tsc` と Lint で落とす方が確実です。

---

## 5. 設定では閉じない「縦のリスク」：aegis fix --format json のループ

ここまでの permission・hooks・CLAUDE.md は強力ですが、**閉じられる範囲には正直な境界があります**。これらが自動化・強制できるのは「水平の統制」——アプリ横断で一律に効く、ヘッダー/CSP・レート制限・入力検証・CSRF・秘密情報衛生——までです。一方、**「誰が何を所有するか」に依存する縦のリスク**は、設定では閉じません。

| | 水平の統制 | 縦のリスク |
|---|---|---|
| 例 | ヘッダー/CSP・レート制限・入力検証・秘密情報衛生 | 認可/IDOR・BOLA、RLS設計ミス、テナント越境、業務ロジック |
| 性質 | アプリ横断で一律 | アプリ固有の所有権に依存 |
| Claude Codeの設定で | permission・hooks・CLAUDE.mdで自動化・強制できる | 設定では閉じない（設計判断） |
| Aegis scanは | 欠落を検出し、安全な修正を提示 | **検出・警告のみ**（修正はあなたの設計） |

縦のリスクが厄介なのは、**攻撃が「認証も書式も正しい正規リクエスト」だから**です。他人のIDを指す `GET /api/orders/123` は、WAFにもヘッダーにも引っかからない。これはOWASP API Security Top 10で2019年以来ずっと第1位（Broken Object Level Authorization）に居座る、最頻出のクラスです。「認証はするが認可しない」——ログインは通すが、その行がその人のものかを確認しない——という穴が、AI生成のNext.js × Supabaseコードには頻繁に作り込まれます。

どれくらい頻繁か。**公開Supabaseアプリ1,000件の一次調査で、RLSを持つアプリのうち約9.2%が『認証はするが行を所有者に絞らない』ポリシを持っていました**（公開リポジトリ標本ゆえ下限値。所有者非スコープ＝即脆弱ではなく要確認）。手法と全数値は[SupabaseアプリのRLS実地調査](/blog/supabase-rls-security-field-study)に、脆弱→修正の実コードは[RLSの「認証」と「認可」の違い](/blog/supabase-rls-authenticated-vs-authorized-owner-scope-guide)にまとめています。

では、この縦のリスクをClaude Codeのループにどう組み込むか。**設定で閉じるのではなく、「検出→機械可読な修正計画→エージェントに貼る→人間が縦を判断」のループを回します**。

```text
1. scan     npx @aegiskit/cli scan
            └ 水平の欠落 + 縦のリスクの「疑い」を検出
   ↓
2. fix      npx @aegiskit/cli fix --format json
            └ 機械可読（プレーンJSON）の修正計画を出力
   ↓
3. 貼る     その JSON を Claude Code に渡す
            └ 水平の統制は安全な差分として適用させる
   ↓
4. 縦は人間 認可/IDOR・RLS設計は「設計判断」としてあなたに返る
            └ ここは自動修正しない（できない）
```

`aegis fix --format json` が肝です。修正計画がプレーンなJSONなので、Claude Code（でも Cursor でも Codex でも）にそのまま貼って直させられる。水平の統制は「証明可能に安全な変換」だけが適用され、縦のリスク——`USING (true)` が本当に公開意図か、`service_role` 経路に所有権チェックがあるか、`SECURITY DEFINER` 関数の `search_path` が固定されているか——は自動修正されず、設計判断として人間に返ります。

無料のOSSなので、いま試すのが早い。`npx @aegiskit/cli scan`（インストール・設定不要）で、いまのプロジェクトを静的解析できます（[Aegis](/aegis)）。ただし正直に言えば、**scanは「完全な防護」を謳いません**。クリーンな結果は「よくある罠は踏んでいない」であって「このコードは安全だ」ではない。水平の統制は自動化し、縦のリスクは検出・警告にとどめ、閉じるのはあなたの設計——この境界を誤魔化さないのが、セキュリティツールとしての誠実さです。買い手側の視点で診断の枠組みを整理した[AI生成コードの脆弱性診断](/blog/ai-generated-code-vulnerability-assessment-vibe-coding-security-guide)と、[本番化のハードニング](/blog/vibe-coding-ai-generated-code-production-hardening-guide)も、あわせて設計の助けになります。

---

## 6. 三層を一枚に：ローカルループ → CI → 監査

最後に、②のエージェント設定を、①方法論・③CIと1枚につなぎます。守りは「近い順」に重ねるのが効率的です。

```text
[Claude Code ローカルループ]   ← 本記事（②）
  permission(deny先行) + hooks(scan自動発火/Stopゲート) + CLAUDE.md(規約固定)
        │  近い砦：Claudeが書いた瞬間に検出。手戻りを削る
        ▼
[CI ゲート]                     ← 品質ゲート（③）
  aegis ci(SARIF) + 型 + テスト + 静的解析 + 秘密情報スキャン
        │  遠い最後の砦：高信頼の検出だけがビルドを止める
        ▼
[縦のリスク]                    ← 設計判断（設定でもCIでも閉じない）
  認可/IDOR・RLS設計・テナント分離 → 設計レビュー / 監査で塞ぐ
```

近い砦（hooks）で速く潰し、遠い砦（CI）で取りこぼしを止め、それでも残る縦のリスクは設計で閉じる。**速さの源泉は、賢いプロンプトではなく、この設定を先に固めることにあります。** 設定が固まっているから、生成の速度をそのまま出荷の速度にできる。一人 × 生成AIで本番品質のプロダクトを出し続けてこられたのは、この規律のおかげです。

「AIで速く作りたいが、本番のセキュリティを犠牲にしたくない」——その両立は、モデルの選択ではなく、`settings.json` と `CLAUDE.md` の設計で決まります。検証ファーストのローカルループとCIゲートの構築、そして設定では閉じない縦のリスク（認可/IDOR・RLS設計）の設計レビューを、既存プロジェクトへの導入を含めてお引き受けします。

---

## まとめ：エージェントの設定が、本番品質を決める

Claude Codeを本番運用に耐えさせるために、押さえるべきは次の通りです。

1. **分岐点はプロンプトではなく設定**——permission・hooks・CLAUDE.md を先に固める（②の層）。
2. **permission は deny を先に書く**——秘密情報とネットワーク発信を fail-closed に閉じ、最小権限で走らせる。`service_role` の境界は鍵の置き場所。
3. **hooks で scan を発火させる**——CLAUDE.md（助言）で祈らず、PostToolUse で自動検出、Stop で検証を通るまで止める。
4. **CLAUDE.md は規約を固定するが、肥大させない**——決定的に守りたいものは hook へ、機械判定できるものは CI へ昇格させる。
5. **縦のリスクは設定では閉じない**——`aegis fix --format json` で機械可読な計画をエージェントに渡し、認可/IDOR・RLS設計は人間が設計で塞ぐ。
