跳至主要內容

Claude Code 安全優先開發

如何確保您的 Claude Code 工作流程產生安全的程式碼。從 security-auditor agent 到 PreToolUse hooks 和自動化審計。

2026 年 10 月 21 日更新: 補上 2026 年的權限模式預設值(互動式 session 自 v2.1.283 起以 auto 模式啟動、claude -p 自 v2.1.302 起以 Manual 模式啟動)、Bash sandbox 設定、--restricted 與 permissions.blockReadsOutsideWorkingDirectories;釐清 security-auditor 是自訂 subagent(內建的檢查指令是 /security-review);依官方文件修正 prompt hook 與結束碼的寫法;並更新 managed settings 路徑與模型。

AI 輔助開發帶來一個重要問題:如何確保 Claude 編寫的程式碼是安全的?

答案不是避免使用 AI 輔助,而是使用 Claude Code 的官方工具將安全性融入您的工作流程:權限模式與規則、Bash sandbox、hooks、內建的 /security-review 指令,再加上自訂的 security-auditor subagent。

本指南涵蓋如何使用官方功能配置 Claude Code 進行安全意識開發。

官方安全工具

security-auditor Agent

security-auditor 並不是內建的 agent,而是你自己定義的自訂 subagent(Claude Code 內建的 subagent 是 Explore、Plan 與 general-purpose)。若想不做任何設定就立即檢查,可以執行內建的 /security-review 指令,它會審查目前分支的變更是否有漏洞。要建立這個 subagent,請新增如下檔案:

---
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*)"
    ]
  }
}

權限模式語法:

  • 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 年有了變化:

  • 互動式 session 以 auto 模式啟動。 自 Claude Code v2.1.283 起,沒有設定權限模式的終端機與 VS Code session 會以 auto 模式啟動:由一個分類器模型代替你審查每個動作,而不是逐一詢問。明確的 ask 規則仍會跳出詢問,組織也可以關閉 auto 模式。
  • 非互動執行以 Manual 模式啟動。 自 v2.1.302 起,沒有設定模式的 claude -p 與 Agent SDK 執行會以 Manual 模式(設定值為 default)啟動,任何需要核准的呼叫都會被拒絕,除非有 allow 規則、hook 或 --permission-prompt-tool 核准。
  • 受保護路徑依然受到保護。 對 .git、.claude、shell 啟動檔與 .mcp.json 等路徑的寫入,在 Manual 與 acceptEdits 模式會詢問你、在 auto 模式交給分類器判斷、在 dontAsk 模式直接拒絕;設定檔中的 allow 規則無法預先核准這些寫入。

對於敏感的儲存庫,請固定起始模式,並讓檔案工具留在專案內:

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

"default" 就是 Manual 模式,會在編輯、執行 shell 指令與存取網路前詢問。專案的 .claude/settings.json 可以設定 auto 與 bypassPermissions 以外的任何起始模式。blockReadsOutsideWorkingDirectories(v2.1.257+)會讓 Read、Grep、Glob 與 LSP 在每一種模式(包括 bypassPermissions)下都拒絕讀取工作目錄以外的路徑;任何一個設定檔設為 true 就會生效,所以儲存庫可以替自己開啟,卻無法關掉你的設定。管理員可以在 managed settings 中把 permissions.disableAutoMode 與 permissions.disableBypassPermissionsMode 設為 "disable",移除 auto 模式或 bypass 模式。

Sandbox 與 Restricted 模式

權限規則管的是 Claude 的工具;Bash sandbox 則在作業系統層級限制 Claude 執行的 shell 指令(macOS、Linux 與 WSL2)。它預設關閉:執行 /sandbox,或在設定中開啟:

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

failIfUnavailable 會在 sandbox 無法啟動時讓 Claude Code 直接結束,而不是在 sandbox 外執行指令;allowUnsandboxedCommands: false(嚴格 sandbox 模式)則禁止 Claude 把被擋下的指令改到 sandbox 外重試。Sandbox 只涵蓋 shell 指令;檔案工具、hooks 與本機 MCP 伺服器都在 sandbox 之外執行,並遵循權限規則。

在評估用的測試環境或共用機器上,請以 --restricted(或 CLAUDE_CODE_RESTRICTED=1,v2.1.248+)啟動 Claude Code。它會移除會執行指令或程式碼的內建工具與 WebFetch(除非你在 --tools 中指名),讓檔案工具只能存取工作目錄,忽略使用者、專案與本機設定,並拒絕 bypassPermissions。

安全挑戰

當 Claude 編寫程式碼時,存在幾個風險:

  • 從訓練資料複製的不安全模式
  • 缺少輸入驗證
  • 洩露資訊的不當錯誤處理
  • 硬編碼的憑證或密鑰
  • SQL injection、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 Tool 實作

// 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": {
    "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 Injection

有漏洞的:

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
      }]
    }]
  }
}

Cross-Site Scripting (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

預提交安全檢查

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

Stop hook 以結束碼 2 結束時,會把 hook 的 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/ 中自訂的 subagent。

自動化安全測試套件

// 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 的優先序高於命令列、local、專案與使用者設定。

企業層(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最高智能

修正自己程式碼中的 bug 對這些模型而言是日常工作,但以安全為主題的請求可能會碰到安全防護機制。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 模型安全分類器標記的請求(最常見於資安領域)會觸發自動模型 fallback,滲透測試這類攻擊性安全工作更是經常觸發。對於這類工作,Anthropic 建議組織洽詢其受信任存取計畫,例如 Cyber Verification Program。

快速模型切換(v2.0.65+):在提示時按 Option+P(macOS)或 Alt+P(Windows/Linux)。

開始行動

今天:

  1. 在 CLAUDE.md 中添加 security-auditor 委派規則
  2. 為敏感檔案配置權限拒絕
  3. 為危險指令添加一個 PreToolUse hook
  4. 對目前分支執行 /security-review

本週:

  1. 實作用於安全驗證的 Stop hook
  2. 添加安全測試套件
  3. 對關鍵模組執行 security-auditor

本月:

  1. 部署預提交安全 hooks
  2. 在 CI/CD 中整合安全掃描
  3. 培訓團隊進行安全優先開發

安全是一段旅程,而非終點。透過 Claude Code 的 agents 和 hooks,您可以自動化安全最佳實踐。

資料來源:Claude Code 文件、安全性、權限模式、Sandboxing、Hooks 文件、Claude Code GitHub