メインコンテンツへスキップ

Claude Code によるセキュリティファースト開発

Claude Code ワークフローで安全なコードを生成する方法。security-auditor agent から PreToolUse hooks、自動監査まで。

2026年10月21日更新: 2026 年の権限モードのデフォルト(インタラクティブセッションは v2.1.283 以降 auto モード、claude -p は v2.1.302 以降 Manual モード)、Bash サンドボックスの設定、--restricted、permissions.blockReadsOutsideWorkingDirectories を追記しました。security-auditor が組み込みではなくカスタムサブエージェントであること(組み込みのチェックは /security-review)を明確にし、Hook の例を公式の prompt hook と終了コードの仕様に合わせ、managed settings のパスとモデルも更新しています。

AI 支援開発において重要な疑問があります:Claude が書くコードの安全性をどう確保するか?

答えは AI 支援を避けることではありません。Claude Code の公式機能である権限モードとルール、Bash サンドボックス、hooks、組み込みの /security-review コマンド、そしてカスタムの security-auditor サブエージェントを使って、ワークフローにセキュリティを組み込むことです。

このガイドでは、公式機能を使用してセキュリティを意識した開発のために Claude Code を設定する方法を説明します。

公式セキュリティツール

security-auditor Agent

security-auditor は組み込みのエージェントではなく、自分で定義するカスタムサブエージェントです(Claude Code の組み込みサブエージェントは Explore、Plan、general-purpose です)。設定なしですぐにチェックしたい場合は、現在のブランチの変更を脆弱性の観点でレビューする組み込みコマンド /security-review を実行してください。サブエージェントを作るには、次のようなファイルを追加します。

---
name: security-auditor
description: Reviews code changes for security vulnerabilities. Use for auth, payment, and admin changes.
tools: Read, Glob, Grep
model: sonnet
---

You are a security auditor. Check changes for OWASP Top 10 issues,
hardcoded secrets, injection, XSS, and authentication bypasses, and
report each finding with its severity.

これを .claude/agents/security-auditor.md として保存します。Claude は Agent ツール(v2.1.63 より前は Task)経由で委譲します。

Agent({
  subagent_type: "security-auditor",
  model: "sonnet",  // or "opus" for critical code
  prompt: `
    Audit the authentication module for security vulnerabilities.
    Check for:
    - OWASP Top 10 vulnerabilities
    - Hardcoded secrets
    - SQL injection patterns
    - XSS vulnerabilities
    - Authentication bypass risks
  `
})

security-auditor を使用するタイミング:

シナリオモデル理由
認証/決済の変更Sonnet/Opusクリティカルなコード
新しい API エンドポイントSonnet入力検証
ファイルアップロード処理Sonnetサニタイズ
外部 API 連携Sonnetデータ漏洩防止

自動セキュリティ適用のための Hooks

公式 hooks ドキュメントによると、hooks は手動介入なしでセキュリティポリシーを自動的に適用します。

PreToolUse Hook - 危険な操作のブロック

.claude/settings.json で設定:

{
  "hooks": {
    "PreToolUse": [{
      "matcher": "Bash",
      "hooks": [{
        "type": "prompt",
        "prompt": "If the command contains destructive operations (rm -rf, DROP TABLE, git push --force), respond with {\"ok\": false, \"reason\": \"Destructive command: confirm with the user first\"}. Otherwise respond with {\"ok\": true}.",
        "continueOnBlock": true
      }]
    }]
  }
}

prompt hook が返せるのは {"ok": true} か {"ok": false, "reason": "..."} だけです。PreToolUse では ok: false でその呼び出しが拒否され、continueOnBlock: true を付けると理由が Claude に返されて方針を調整できます。特定のコマンドの前に Claude Code から確認させたい場合は、permissions.ask に "Bash(git push --force *)" のような ask ルールを追加します。

利用可能な hook イベント:

イベントタイミングセキュリティ用途
PreToolUseツール実行前危険なコマンドのブロック
PostToolUseツール実行後ファイル変更の監査
StopClaude が応答を終えたときセキュリティレビューの確認
SessionStartセッション開始時セキュリティコンテキストの読み込み

Stop Hook - セキュリティレビューの確認

{
  "hooks": {
    "Stop": [{
      "hooks": [{
        "type": "agent",
        "prompt": "Run git diff --name-only. If files in auth/, payment/, or admin/ changed and the transcript shows no security-auditor review, respond with {\"ok\": false, \"reason\": \"Run the security-auditor subagent on the changed files before finishing\"}. Otherwise respond with {\"ok\": true}. $ARGUMENTS"
      }]
    }]
  }
}

prompt hook は Hook の入力しか見られないため、このチェックにはコマンドを実行して履歴を読める agent hook を使っています。agent hook は実験的機能です。Stop で ok: false を返すと、その理由を次の指示として Claude が作業を続けます。

Permission Settings

Claude Code ドキュメントによると、settings.json でアクセス制御を行います:

{
  "permissions": {
    "allow": [
      "Read",
      "Write",
      "Edit",
      "Bash(npm run *)",
      "Bash(git *)"
    ],
    "deny": [
      "Read(.env)",
      "Read(.env.*)",
      "Read(secrets/**)",
      "Read(**/*credentials*)",
      "Bash(*rm -rf*)",
      "Bash(*DROP*)"
    ]
  }
}

Permission パターン構文:

  • Bash(npm run *) - すべての npm run コマンドを許可(Bash(npm run:*) は同等の旧表記)
  • Read(.env) - .env ファイルの読み取りを拒否
  • Read(secrets/**) - secrets/ 内のすべての読み取りを拒否
  • Bash(*DROP*) - DROP を含むコマンドを拒否

ルールは deny → ask → allow の順に評価され、deny ルールは bypassPermissions を含むすべての権限モードで有効です。ファイルパスのルールは Read(...) または Edit(...) で書きます。Claude Code は Write(パス) ルールを一切チェックしません。

権限モードとデフォルト(2026)

権限モードは Claude が行動前に確認するかどうかを決めるもので、2026 年にデフォルトが変わりました。

  • インタラクティブセッションは auto モードで開始。 Claude Code v2.1.283 以降、権限モードが設定されていないターミナルと VS Code のセッションは auto モードで始まり、分類器モデルがユーザーの代わりに各アクションを審査します。明示的な ask ルールは引き続き確認を求め、組織は auto モードを無効化できます。
  • ヘッドレス実行は Manual モードで開始。 v2.1.302 以降、モードが設定されていない claude -p と Agent SDK の実行は Manual モード(設定値は default)で始まり、承認が必要な呼び出しは allow ルール、hook、--permission-prompt-tool のいずれかが承認しない限り拒否されます。
  • 保護されたパスは引き続き保護される。 .git、.claude、シェルの起動ファイル、.mcp.json などへの書き込みは、Manual と acceptEdits では確認を求め、auto では分類器に回され、dontAsk では拒否されます。設定ファイルの allow ルールでは事前承認できません。

機密性の高いリポジトリでは、開始モードを固定し、ファイルツールをプロジェクト内に留めます。

{
  "permissions": {
    "defaultMode": "default",
    "blockReadsOutsideWorkingDirectories": true
  }
}

"default" は Manual モードで、編集・シェルコマンド・ネットワークアクセスの前に確認します。プロジェクトの .claude/settings.json では auto と bypassPermissions 以外の開始モードを指定できます。blockReadsOutsideWorkingDirectories(v2.1.257 以降)は、bypassPermissions を含むすべてのモードで Read、Grep、Glob、LSP に作業ディレクトリ外のパスを拒否させます。いずれかの設定ファイルで true になっていれば適用されるため、リポジトリ側で有効化はできても、あなたの設定を無効化することはできません。管理者は managed settings で permissions.disableAutoMode と permissions.disableBypassPermissionsMode を "disable" にして、auto モードや bypass モードを取り除けます。

サンドボックスと Restricted モード

権限ルールは Claude のツールを制御しますが、Bash サンドボックスは Claude が実行するシェルコマンドを OS レベルで制限します(macOS、Linux、WSL2)。デフォルトはオフで、/sandbox を実行するか設定で有効にします。

{
  "sandbox": {
    "enabled": true,
    "failIfUnavailable": true,
    "allowUnsandboxedCommands": false,
    "filesystem": {
      "denyRead": ["~/.aws/credentials"]
    },
    "network": {
      "allowedDomains": ["github.com", "*.npmjs.org"]
    }
  }
}

failIfUnavailable を付けると、サンドボックスを起動できないときにコマンドを非サンドボックスで実行せず Claude Code が終了します。allowUnsandboxedCommands: false(strict sandbox モード)は、ブロックされたコマンドをサンドボックス外で再試行することを禁止します。サンドボックスの対象はシェルコマンドだけで、ファイルツール、hooks、ローカルの MCP サーバーはその外で動き、権限ルールに従います。

評価用のハーネスや共有マシンでは、--restricted(または CLAUDE_CODE_RESTRICTED=1、v2.1.248 以降)で Claude Code を起動します。コマンドやコードを実行する組み込みツールと WebFetch を(--tools で明示しない限り)取り除き、ファイルツールを作業ディレクトリ内に限定し、ユーザー・プロジェクト・ローカルの設定を無視し、bypassPermissions を拒否します。

セキュリティの課題

Claude がコードを書く際、いくつかのリスクがあります:

  • トレーニングデータからコピーされた安全でないパターン
  • 入力検証の欠如
  • 情報を漏洩する不適切なエラー処理
  • ハードコードされた認証情報やシークレット
  • SQL インジェクション、XSS、その他の脆弱性

解決策:agents と hooks を使ってセキュリティ要件をコード化し、Claude が自動的にそれらに従うようにすることです。

セキュリティファースト CLAUDE.md の構築

セキュリティセクションテンプレート

# Security Requirements

## Non-Negotiables
These rules cannot be overridden for any reason:

1. **No Secrets in Code**
   - Never hardcode credentials, API keys, or tokens
   - Use environment variables for all secrets
   - Reference secrets through secure config management

2. **Input Validation**
   - All user inputs must be validated
   - Use allowlist validation over blocklist
   - Validate on both client and server

3. **Output Encoding**
   - Encode all outputs for the context (HTML, URL, JS)
   - Use framework-provided escaping mechanisms
   - Never concatenate raw user input into responses

4. **Authentication & Authorization**
   - All endpoints must verify authentication
   - Check authorization before every action
   - Use principle of least privilege

5. **Data Protection**
   - Encrypt sensitive data at rest and in transit
   - Minimize data collection and retention
   - Log access to sensitive data

## Security Review Requirements
These types of changes require explicit security review:
- Authentication/authorization logic
- Payment processing
- Personal data handling
- API endpoint creation
- Database queries
- File uploads
- Email sending
- External API calls

入力検証標準

# Input Validation Standards

## Validation Library
Use Zod for all runtime validation:

\`\`\`typescript
import { z } from 'zod';

// Define schema
const UserSchema = z.object({
  email: z.string().email(),
  age: z.number().min(0).max(150),
  name: z.string().min(1).max(100),
});

// Validate
const result = UserSchema.safeParse(input);
if (!result.success) {
  throw new ValidationError(result.error);
}
\`\`\`

## Validation Rules
- String inputs: Define max length
- Numeric inputs: Define valid range
- Email: Use proper email validation
- URLs: Validate protocol and domain
- IDs: Validate format (UUID, numeric, etc.)
- Arrays: Validate length and item types
- Objects: Validate required fields

セキュアコーディングパターン

# Secure Coding Patterns

## Database Queries
ALWAYS use parameterized queries:

\`\`\`typescript
// NEVER do this
const query = \`SELECT * FROM users WHERE email = '\${email}'\`;

// ALWAYS do this
const user = await db.user.findUnique({
  where: { email }, // Prisma handles parameterization
});
\`\`\`

## Error Handling
Never expose internal details:

\`\`\`typescript
// NEVER do this
catch (error) {
  return res.status(500).json({ error: error.message });
}

// ALWAYS do this
catch (error) {
  console.error('Internal error:', error); // Log full error
  return res.status(500).json({ error: 'An error occurred' }); // Generic message
}
\`\`\`

## Authentication Checks
Always verify auth at the start:

\`\`\`typescript
export async function handler(req, res) {
  // First: Authenticate
  const user = await getAuthenticatedUser(req);
  if (!user) {
    return res.status(401).json({ error: 'Unauthorized' });
  }

  // Second: Authorize
  if (!user.canAccessResource(resourceId)) {
    return res.status(403).json({ error: 'Forbidden' });
  }

  // Then: Proceed with logic
  // ...
}
\`\`\`

セキュリティのための Agent 委譲

機密性の高い変更に対してセキュリティレビューを自動的に実行するよう Claude を設定します:

# Agent Delegation Rules

## Automatic Security Review
These changes automatically trigger security-auditor agent:

- Files in: auth/, payment/, admin/
- Functions containing: password, token, secret, key, credential
- Operations: user creation, permission changes, data deletion
- External calls: API integrations, webhooks, email

## Security Agent Configuration
When security-auditor runs, it checks for:
- OWASP Top 10 vulnerabilities
- Hardcoded secrets
- Missing authentication
- SQL injection patterns
- XSS vulnerabilities
- Insecure direct object references
- Missing rate limiting
- Insufficient logging

Agent ツールでの実装

// Automatic security review for auth changes
Agent({
  subagent_type: "security-auditor",
  model: "sonnet",
  prompt: `
    Review changes to auth/ directory.
    Check for OWASP Top 10 vulnerabilities:
    1. Injection
    2. Broken authentication
    3. Sensitive data exposure
    4. XML external entities
    5. Broken access control
    6. Security misconfiguration
    7. Cross-site scripting
    8. Insecure deserialization
    9. Using components with known vulnerabilities
    10. Insufficient logging

    Report findings with severity levels.
  `
})

セキュリティワークフローパターン

パターン 1:実装前レビュー

セキュリティに関わるコードを書く前に:

Agent({
  subagent_type: "security-auditor",
  model: "sonnet",
  prompt: `
    Planning to implement password reset functionality.
    Review security considerations:
    1. What vulnerabilities should I address?
    2. What OWASP vulnerabilities are relevant?
    3. What's the secure implementation pattern?
    4. What tests should I write?
  `
})

パターン 2:自動 hooks を使った実装

自動 hooks を使った実装時:

{
  "hooks": {
    "PostToolUse": [{
      "matcher": "Edit|Write",
      "hooks": [{
        "type": "prompt",
        "prompt": "If tool_input.file_path is in an auth/, payment/, or admin/ directory, respond with {\"ok\": false, \"reason\": \"Security-sensitive file changed: run the security-auditor subagent on it\"}. Otherwise respond with {\"ok\": true}.",
        "continueOnBlock": true
      }]
    }]
  }
}

パターン 3:実装後の監査

実装後:

Agent({
  subagent_type: "security-auditor",
  model: "opus",  // Use Opus for critical security review
  prompt: `
    Comprehensive security audit of password reset feature.

    Check for:
    - Token generation entropy
    - Timing attacks in token comparison
    - Rate limiting bypass
    - User enumeration
    - Session fixation after reset
    - Proper invalidation of old sessions

    Provide findings categorized by severity:
    - Critical
    - High
    - Medium
    - Low
  `
})

一般的な脆弱性と予防

SQL インジェクション

脆弱なコード:

const query = `SELECT * FROM users WHERE id = ${userId}`;

安全なコード:

const user = await prisma.user.findUnique({ where: { id: userId } });

Hook による保護:

{
  "hooks": {
    "PreToolUse": [{
      "matcher": "Edit|Write",
      "hooks": [{
        "type": "prompt",
        "prompt": "If the new code builds SQL by concatenating strings with SQL keywords (SELECT, INSERT, UPDATE, DELETE), respond with {\"ok\": false, \"reason\": \"Possible SQL injection: use parameterized queries\"}. Otherwise respond with {\"ok\": true}.",
        "continueOnBlock": true
      }]
    }]
  }
}

クロスサイトスクリプティング(XSS)

脆弱なコード:

<div dangerouslySetInnerHTML={{ __html: userContent }} />

安全なコード:

<div>{userContent}</div> // React auto-escapes

CLAUDE.md ルール:

## XSS Prevention
- Never use dangerouslySetInnerHTML without sanitization
- Use DOMPurify for HTML content that must be rendered
- Escape all dynamic content in non-React contexts

認証バイパス

脆弱なコード:

if (user.role === 'admin') {
  // Allow action
}

安全なコード:

if (await authService.hasPermission(user.id, 'admin:action')) {
  // Allow action
}

機密データの露出

脆弱なコード:

return res.json({ user }); // Includes password hash!

安全なコード:

return res.json({ user: sanitizeUser(user) });

継続的セキュリティのための Hooks

Pre-Commit セキュリティチェック

{
  "hooks": {
    "Stop": [{
      "hooks": [{
        "type": "command",
        "command": "npm run security-scan >&2 || exit 2"
      }]
    }]
  }
}

Stop hook が終了コード 2 を返すと、その stderr が理由として渡され、Claude は作業に戻ります。onFailure: "block" フィールド(v2.1.295 以降)は Stop hook には効かないため、スキャンが失敗したときはコマンド自身が終了コード 2 を返す必要があります。

自動シークレット検出

{
  "hooks": {
    "PreToolUse": [{
      "matcher": "Edit|Write",
      "hooks": [{
        "type": "prompt",
        "prompt": "Scan the new content for potential secrets: API keys, passwords, tokens, private keys. If found, respond with {\"ok\": false, \"reason\": \"Possible secret on lines ...\"}. Otherwise respond with {\"ok\": true}.",
        "continueOnBlock": true
      }]
    }]
  }
}

ファイルアクセス制御

{
  "permissions": {
    "deny": [
      "Read(.env*)",
      "Read(**/secrets/**)",
      "Read(**/*credential*)",
      "Read(**/*.pem)",
      "Read(**/*.key)",
      "Edit(.env*)",
      "Edit(**/secrets/**)"
    ]
  }
}

test-runner によるセキュリティテスト

security-auditor と同じく、test-runner も .claude/agents/ に自分で定義するカスタムサブエージェントです。

自動セキュリティテストスイート

// Launch parallel security tests
Agent({
  subagent_type: "test-runner",
  model: "haiku",
  prompt: "Run all security-related tests in tests/security/"
})

Agent({
  subagent_type: "security-auditor",
  model: "sonnet",
  prompt: "Verify test coverage for authentication edge cases"
})

セキュリティテスト例

describe('Password Reset Security', () => {
  it('rejects invalid tokens', async () => {
    const response = await request(app)
      .post('/api/auth/reset-password')
      .send({ token: 'invalid', password: 'newpassword' });

    expect(response.status).toBe(400);
    expect(response.body).not.toContain('token');
  });

  it('prevents timing attacks on token validation', async () => {
    // Use constant-time comparison
    const times = [];
    for (let i = 0; i < 100; i++) {
      const start = performance.now();
      await validateToken(`token${i}`);
      times.push(performance.now() - start);
    }
    // Variance should be minimal
    expect(standardDeviation(times)).toBeLessThan(5);
  });

  it('rate limits reset requests', async () => {
    const email = 'test@example.com';

    // First 3 requests succeed
    for (let i = 0; i < 3; i++) {
      const response = await request(app)
        .post('/api/auth/forgot-password')
        .send({ email });
      expect(response.status).toBe(200);
    }

    // 4th request is rate limited
    const response = await request(app)
      .post('/api/auth/forgot-password')
      .send({ email });
    expect(response.status).toBe(429);
  });
});

セキュリティ監査チェックリスト

デプロイ前に:

## Pre-Deployment Security Checklist

### Authentication
- [ ] All endpoints require authentication (except public ones)
- [ ] Tokens expire appropriately
- [ ] Password requirements enforced
- [ ] Account lockout after failed attempts

### Authorization
- [ ] Permission checks on all protected actions
- [ ] No privilege escalation paths
- [ ] Admin functions properly protected

### Data Protection
- [ ] Sensitive data encrypted at rest
- [ ] HTTPS enforced
- [ ] No secrets in code or logs
- [ ] PII handling compliant

### Input/Output
- [ ] All inputs validated
- [ ] All outputs properly encoded
- [ ] File uploads validated and sanitized
- [ ] No SQL injection vulnerabilities

### Logging & Monitoring
- [ ] Security events logged
- [ ] Logs don't contain sensitive data
- [ ] Alerting configured for anomalies

エンタープライズセキュリティ機能

Claude Code は設定の階層を通じてエンタープライズセキュリティ要件をサポートします。managed settings はコマンドライン、ローカル、プロジェクト、ユーザー設定より優先されます。

Enterprise Layer(Managed Settings)

// /etc/claude-code/managed-settings.json(Linux と WSL、IT 管理)
{
  "permissions": {
    "deny": [
      "Bash(*curl*)",
      "Bash(*wget*)",
      "Read(//etc/**)",
      "Edit(//etc/**)"
    ],
    "disableBypassPermissionsMode": "disable"
  },
  "allowedMcpServers": [
    { "serverName": "filesystem" },
    { "serverName": "memory" }
  ]
}

macOS では /Library/Application Support/ClaudeCode/managed-settings.json、Windows では C:\Program Files\ClaudeCode\managed-settings.json に置きます。Read と Edit のルールで絶対パスを書くときは // で始めます。

監査ログ設定

## Audit Requirements
Log these events to secure audit system:
- Authentication attempts (success/failure)
- Authorization decisions
- Data access (especially sensitive data)
- Configuration changes
- API calls to external services

コンプライアンス統合

## Compliance Requirements
- PCI DSS: No card data in logs, encrypt at rest
- GDPR: Data minimization, right to deletion
- HIPAA: PHI access controls and audit trails
- SOC 2: Change management documentation

セキュリティのためのモデル選択

Claude Code のモデル設定ドキュメントより:

タスク推奨モデル理由
クイックセキュリティスキャンHaiku 5.5高速パターンマッチング
コードレビューSonnet 5.5バランスの取れた分析
セキュリティ監査Opus 5.5徹底的なレビュー。脆弱性探索には max effort が推奨されている
クリティカルセキュリティFable 5.1最高の知性

自分のコードのバグ修正はこれらのモデルにとって日常的な作業ですが、セキュリティを主題とするリクエストはセーフガードに当たることがあります。Anthropic の Opus 5.5 発表記事にはこうあります:「Users will be able to identify and fix bugs in their code as part of the routine software development lifecycle, but most cybersecurity tasks will be re-routed to Opus 4.8.」(出典)Fable モデルの安全分類器が(多くはサイバーセキュリティ領域で)フラグを立てたリクエストは自動モデルフォールバックを引き起こし、ペネトレーションテストのような攻撃的セキュリティ作業では頻繁に発生します。そうした用途について、Anthropic は Cyber Verification Program などの信頼アクセスプログラムへの相談を案内しています。

クイックモデル切り替え(v2.0.65+):プロンプト入力中に Option+P(macOS)または Alt+P(Windows/Linux)を押します。

はじめに

今日:

  1. CLAUDE.md に security-auditor 委譲ルールを追加
  2. 機密ファイルに対する permission denials を設定
  3. 危険なコマンドに対する PreToolUse hook を 1 つ追加
  4. 現在のブランチで /security-review を実行

今週:

  1. セキュリティ検証のための Stop hook を実装
  2. セキュリティテストスイートを追加
  3. クリティカルモジュールに対して security-auditor を実行

今月:

  1. pre-commit セキュリティ hooks をデプロイ
  2. CI/CD にセキュリティスキャンを統合
  3. チームにセキュリティファースト開発をトレーニング

セキュリティは目的地ではなく旅です。Claude Code の agents と hooks を使えば、セキュリティのベストプラクティスを自動化できます。

参考:Claude Code Documentation、Security、権限モード、Sandboxing、Hooks Documentation、Claude Code GitHub