---
title: "Claude Code 安全三道防线：从权限模式到 Hook 兜底的纵深防护实战"
author: deletexiumu
pubDatetime: 2026-03-07T18:00:00+08:00
featured: false
draft: false
tags:
  - Claude Code
  - AI Agent
  - 教程
description: "从一次真实生产数据库误删事故出发，详解 Claude Code 三层安全防护体系：权限模式+规则+沙箱、Discernment 门禁、Hook 兜底拦截。附完整可复制的配置文件和经过实测的拦截脚本。"
---

## 一、开篇：一条命令，2.5 年数据灰飞烟灭

2025 年底，DataTalks.Club 创始人 Alexey Grigorev 写了一篇让整个 AI 编程社区倒吸冷气的复盘文章：他让 Claude Code 执行 Terraform 操作，结果摧毁了整个生产环境。

VPC、RDS 数据库、ECS 集群、负载均衡器、堡垒机，全部删除。`courses_answer` 表里的 **1,943,200 行数据**、RDS 自动快照一并消失，平台宕机 24 小时。

为了找回数据，他半夜紧急升级 AWS Business Support，月费多了 10%。最后是 AWS 内部团队找到了一个对用户不可见的快照，才把数据救回来。

这不是一次简单的"AI 执行了错误命令"。复盘下来，是**五个错误环环相扣**，最终酿成灾难：

**错误一：共用 Terraform 配置。** 为了省 5-10 美元/月，Alexey 把新项目加入了已有的 Terraform 配置中，新旧基础设施混在一起。

**错误二：忽略 State 文件缺失。** 换了新电脑，旧电脑上的 Terraform state 文件没迁过来。运行 `terraform plan` 时，Terraform 误以为基础设施从零开始，生成了一堆"创建"操作。发现异常后虽然叫停了，但部分资源已经创建。

**错误三：委托 AI 清理"重复资源"。** 让 Claude Code 通过 AWS CLI 识别并删除"新创建的重复资源"。同时从旧电脑取回了 Terraform 归档文件（里面有真实的 state），交给 agent 做比对。

**错误四：AI 用旧 State 覆盖了当前 State。** Claude 在操作过程中解压了旧归档，用旧的 state 文件替换了当前 state。此时 state 指向的是真实的生产基础设施。这个操作发生在文件系统层面，没有任何拦截。

**错误五：批准 `terraform destroy`。** Agent 表示 AWS CLI 删除太复杂，建议改用 `terraform destroy`。Alexey 觉得"逻辑合理"，点了同意。然后一切都没了。

> "terraform destroy 看起来逻辑合理，所以我批准了。" —— Alexey Grigorev

核心问题不是 AI 太蠢——恰恰相反，每一步操作"看起来都合理"。问题在于：**我们给了它太多权限，却没有安全网。**

---

## 二、为什么 AI Agent 自动化特别危险？

先厘清两类完全不同的风险，不要混为一谈：

**代码生成风险**——AI 写出的代码本身含漏洞。Veracode 测试了超过 100 个大语言模型的 80 个代码补全任务，结果 **45% 的测试用例中，LLM 引入了 OWASP Top 10 级别的安全漏洞**。（来源：[Veracode 2025 GenAI Code Security Report](https://www.veracode.com/resources/analyst-reports/2025-genai-code-security-report/)）

具体到语言和漏洞类型：
- Java 安全失败率最高，超过 **70%**
- 跨站脚本（CWE-80）在 **86%** 的情况下生成不安全代码
- 日志注入（CWE-117）在 **88%** 的情况下生成不安全代码

**自主执行风险**——AI Agent 自主决策并执行破坏性操作。这是本文的重点。

两者的区别：代码生成风险可以靠代码审查和安全扫描兜底；自主执行风险一旦发生，命令已经跑完了，没有"回滚"的机会。

### 确定性脚本 vs 概率性 Agent

传统自动化脚本是**确定性的**——写什么执行什么，行为可预测。

AI Agent 闭环是**概率性的**——AI 生成命令 → AI 看输出 → AI 决定下一步 → 人只在最后点"同意"。每次运行的决策路径可能不同。

| 维度 | 确定性脚本 | AI Agent 闭环 |
|------|-----------|--------------|
| 行为可预测性 | 高——写什么跑什么 | 低——每次决策路径可能不同 |
| 错误类型 | 代码 bug，可复现 | 决策偏差，难复现 |
| 人类审查点 | 写脚本时审查一次 | 每次运行都要审查（但往往不看） |
| 破坏速度 | 取决于脚本内容 | 极快——AI 几秒内连续执行十几条命令 |
| 上下文理解 | 脚本作者编码了上下文 | AI 不知道生产 vs 测试（除非你告诉它） |

三个特性让自主执行风险格外危险：

1. **速度快**：AI 几秒内可以连续执行十几条命令，人来不及审查。
2. **上下文丢失**：AI 不知道哪个是生产环境、哪个是测试环境——除非你在 prompt 里明确告诉它。
3. **自信且不犹豫**：AI 不会像人一样在 `rm -rf` 前手抖。

### 不只是 Alexey

同类事故频发：

- **Google Antigravity AI 删除用户整个硬盘**（2025.12）：开发者启用了 Turbo mode（YOLO 模式），AI 在清除缓存时执行了 `rmdir /s /q d:\`，整个 D 盘被删除，图片、视频永久丢失。AI 事后试图"修复"，反而把情况搞得更糟。（来源：[Tom's Hardware](https://www.tomshardware.com/tech-industry/artificial-intelligence/googles-agentic-ai-wipes-users-entire-hard-drive-without-permission-after-misinterpreting-instructions-to-clear-a-cache-i-am-deeply-deeply-sorry-this-is-a-critical-failure-on-my-part)）

- **Replit AI Agent 删除生产数据库**（2025.7）：AI 在活跃的代码冻结期间，无视反复指示，删除了线上生产数据库。事后还对删除行为**撒谎**。Replit CEO 称事件"不可接受"。（来源：[Fortune](https://fortune.com/2025/07/23/ai-coding-tool-replit-wiped-database-called-it-a-catastrophic-failure/)）

- **Meta 超级智能安全总监**的 AI agent（OpenClaw）差点清空了她的整个邮箱。（来源：[Fast Company](https://www.fastcompany.com/91497841/meta-superintelligence-lab-ai-safety-alignment-director-lost-control-of-agent-deleted-her-emails)）

这些案例有一个共同点：不是 AI 恶意为之，而是在自动化执行的闭环中，**一个"看起来合理"的决策滚雪球式地演变成灾难**。Alexey 的那句话说得最准确——"terraform destroy 看起来逻辑合理，所以我批准了"。

---

## 三、第一道防线：权限模式 + 权限规则 + 沙箱边界

Claude Code 内置了一套权限控制体系。这是最基础的防线。

### 五种权限模式

| 模式 | 标识符 | 说明 |
|------|--------|------|
| 标准模式 | `default` | 首次使用每个工具时弹出确认提示 |
| 自动接受编辑 | `acceptEdits` | 文件编辑自动执行，Bash 仍需确认 |
| 计划模式 | `plan` | 只能分析，不能修改文件或执行命令 |
| 静默拒绝 | `dontAsk` | 未经 `/permissions` 预授权的工具自动拒绝 |
| 跳过所有确认 | `bypassPermissions` | 跳过全部权限检查——Dangerous 模式 |

`bypassPermissions` 就是 Alexey 事故的放大器。官方文档对它有显著警告：**仅限容器、VM 等隔离环境使用**。

在 `settings.json` 中设置默认模式：

```json
{
  "defaultMode": "acceptEdits"
}
```

通过 CLI 临时切换：

```bash
# 计划模式——只读分析，不执行任何操作
claude --default-mode plan

# 静默拒绝——未预授权的工具自动拒绝
claude --default-mode dontAsk

# Dangerous 模式——跳过所有权限提示（别在生产环境用）
claude --dangerously-skip-permissions
```

### 权限规则系统

通过 `/permissions` 菜单可以精细配置三级规则：

- **Allow**：自动放行，无需确认
- **Ask**：每次弹窗确认
- **Deny**：直接禁止

优先级：**deny > ask > allow**，第一个匹配的规则生效。

实际配置示例——允许常见的只读 git 命令，但拒绝强制推送：

```
Allow: Bash(git status)
Allow: Bash(git diff)
Allow: Bash(git log*)
Deny: Bash(git push --force*)
Deny: Bash(git push -f*)
```

### 沙箱与目录边界

- 工作目录范围限制：通过 deny 规则限制 Read/Edit 的目录范围
- WebFetch 域名限制：控制 AI 可以访问的网络资源
- 管理员可通过托管设置（managed settings）强制禁用 `bypassPermissions`：

```json
{
  "disableBypassPermissionsMode": "disable"
}
```

### 权限体系的局限

**模式粒度仍然较粗——无法理解操作语义。**

对权限系统来说，`terraform destroy` 和 `terraform plan` 没有区别，都是"Bash 命令"。`DROP TABLE users` 和 `SELECT * FROM users` 没有区别，都是"执行 SQL"。权限系统只看工具类型和命令模式，不理解操作的实际影响。

对 MCP 工具的控制同样依赖额外配置——MCP 服务器本身可能带来新的攻击面（对 7,000+ MCP 服务器的分析发现，36.7% 存在 SSRF 漏洞。来源：[MCP Landscape and Security Threats](https://xinyi-hou.github.io/files/hou2025mcp.pdf)）。

**结论：内置权限是必要的底线，但远远不够——它挡得住"明显危险"的操作，挡不住"看起来合理但实际危险"的决策。**

---

## 四、第二道防线：Discernment 门禁——让 AI 自己先三思

权限模式的问题在于：它是一个语法级别的检查，不理解语义。`terraform destroy` 在语法上和 `terraform plan` 没区别。我们需要的是一种**语义级别的风险评估**——在执行高风险任务前，让 AI 自己停下来想想"这个操作真的安全吗？"

这就是 Discernment 门禁的核心思路：不是拦命令，而是在 AI 做出高风险决策之前，强制插入一个风险评估环节。

Discernment 是"软防线"——它靠 AI 的语义理解能力判断风险，通过规则文件（CLAUDE.md / rules/）注入，不需要写代码，纯 prompt 驱动。

### 工作流程

**阶段一：快速风险扫描**

每个任务开始前，Claude 对照触发条件列表做一次快速扫描。未命中 → 跳过，正常执行。命中任一条件 → 进入阶段二。

触发条件示例（我实际使用的配置）：

- 不可逆/高爆炸半径：改生产环境、删数据、影响共享系统、开大权限
- 安全与合规：涉及密钥、权限、网络暴露
- 资金与配额：显著费用、资源扩容、供应商锁定
- 数据正确性：ETL 语义、指标口径、回填重算
- 破坏性命令：terraform apply、kubectl delete、DROP/ALTER、大范围 rm
- 方案选型/架构设计：技术栈选择、架构模式决策

**阶段二：Discernment 审查**

Step 1 —— Claude 出风险草稿（短表单，10 行以内）：
- **失败 Top3**：最可能失败的 3 个原因（含触发条件 + 可观测信号）
- **关键假设**：列出假设及来源（用户提供 / 仓库现状 / 命令输出 / **未验证**）
- **缺失信息**：无法自行补全 → **必须提问阻塞，不得猜测**
- **最小替代**：dry-run / plan / shadow run / 备份回滚等降级方案

Step 2 ——（可选）发送外部模型对抗审查，让第二个 AI 独立评估：
- 3 个可复现失败场景
- 3 个需用户确认的外部事实/约束
- 1 个最小破坏性替代方案

Step 3 —— 综合输出最终 Discernment，标注共识与分歧。

Step 4 —— **用户确认后才进入执行阶段**。

### 完整规则文件

以下是我实际使用的 `~/.claude/rules/discernment.md`，可以直接复制：

```markdown
# Discernment 门禁 — 高风险任务前置审查

## 触发条件（任一命中即触发）
- **不可逆/高爆炸半径**：改生产环境、删数据、影响共享系统、开大权限
- **安全与合规**：涉及密钥、权限、网络暴露、审计
- **资金与配额**：显著费用、资源扩容、供应商锁定
- **数据正确性**：ETL 语义、指标口径、回填重算、下游依赖多
- **破坏性命令**：terraform apply、生产库迁移、kubectl delete、DROP/ALTER、大范围 rm
- **方案选型/架构设计**：技术栈选择、架构模式决策

## 两阶段流程

### 阶段一：快速风险扫描
对当前任务评估是否命中上述条件。未命中 → 跳过，正常执行。

### 阶段二：Discernment 审查（仅高风险触发）

**Step 1 — Claude 出草稿**（短表单，10行以内）：
- 失败 Top3：最可能失败的 3 个原因（含触发条件 + 可观测信号）
- 关键假设：列出假设及来源（用户提供 / 仓库现状 / 命令输出 / 未验证）
- 缺失信息：无法自行补全 → **必须提问阻塞，不得猜测**
- 最小替代：dry-run / plan / shadow run / 备份回滚 等降级方案

**Step 2 — 外部模型对抗审查**（可选）：
独立输出：
- 3 个可复现失败场景（含触发条件与可观测信号）
- 3 个需用户确认的外部事实/约束（不确定就提问，不猜）
- 1 个最小破坏性替代方案（不采用需说明代价）

**Step 3 — 综合输出最终 Discernment**：合并双方意见，标注共识与分歧。

**Step 4 — 用户确认后**才进入执行阶段。

## 用户控制
- 提示中标注 `risk=low` → 跳过 Discernment
- 提示中标注 `risk=high` → 强制触发 Discernment
```

在 `CLAUDE.md` 中只需要一段引用：

```markdown
## Discernment 门禁
- 高风险任务（不可逆、安全、数据正确性、架构选型）执行前，须走 Discernment 审查
- 详细规则 → rules/discernment.md
- 用户可标注 `risk=low` 跳过 / `risk=high` 强制触发
```

### 用 Alexey 案例复盘：Discernment 会拦住哪一步？

假设 Alexey 的 Claude Code 配置了 Discernment 规则。当 Agent 准备执行 `terraform destroy` 时，触发"破坏性命令"条件，进入审查：

**失败 Top3**：
1. State 文件指向错误的基础设施 → 触发条件：state 刚被替换过 → 信号：`terraform plan` 输出与预期不符
2. destroy 范围超出预期 → 触发条件：共用配置包含多套基础设施 → 信号：destroy 列表中出现非目标资源
3. 备份不存在或不可用 → 触发条件：RDS 快照依赖基础设施存在 → 信号：无独立备份确认

**关键假设**：
- State 文件指向的是正确的基础设施 → **来源：未验证** → **必须提问阻塞**
- 只有"重复创建的资源"会被销毁 → 来源：AI 自行判断 → 需要人工确认 destroy 列表

**最小替代**：
- 先跑 `terraform plan` 看影响范围，不直接 destroy
- 用 `terraform state list` 确认 state 指向哪些资源

如果走了这个流程，**错误四（state 被覆盖）和错误五（直接 destroy）大概率会被拦住**。"State 文件来源：未验证"这一条就足以阻塞执行。

### Discernment 的局限

AI 也会犯错。如果 AI 自己判断"这个操作安全"，Discernment 就失效了。提示注入攻击也可能绕过 prompt 级别的规则。所以 Discernment 是必要的，但不是充分的——我们需要一个不依赖 AI 判断的兜底机制。

---

## 五、第三道防线（兜底）：Hook——不管 AI 怎么想，这些命令必须拦

Discernment 靠 AI 的语义理解来判断风险，但 AI 可能漏判。Hook 靠硬编码规则，不依赖 AI 的判断——即使 AI 认为"这次 destroy 是安全的"，Hook 依然会拦截。

最关键的一点：**即使开了 Dangerous 模式（bypassPermissions），Hook 依然生效。** 这是 Hook 作为最后一道安全网的核心依据。

### Hook 是什么

Hook 是 Claude Code 在执行工具调用前/后自动运行的脚本。跟 Git hooks 类似，但触发点是 Claude Code 的工具调用。

与安全最相关的三个事件类型：

| 事件 | 触发时机 | 能否阻断 |
|------|---------|---------|
| `PreToolUse` | 工具执行前 | **能**——最关键的拦截点 |
| `PostToolUse` | 工具执行后 | 否——但可用于审计 |
| `UserPromptSubmit` | 用户提交 prompt 后 | 能——可在 Claude 处理前检查 |

### 实战：构建多路破坏性命令拦截 Hook

需求：拦截 `terraform destroy`、`kubectl delete`、`DROP TABLE`、`rm -rf` 等高危命令。

**关键点：不只拦 Bash。** 破坏性操作可能通过多种路径执行：
- Bash 命令：`terraform destroy`、`rm -rf`
- MCP 工具：数据库 MCP 执行 `DROP TABLE`
- Edit/Write：覆盖 state 文件、修改 `.env` 配置

所以 Hook 需要做**多路拦截**。

#### 配置文件（settings.json）

```json
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": ".claude/hooks/block-dangerous-commands.sh",
            "timeout": 10
          }
        ]
      },
      {
        "matcher": "mcp__.*",
        "hooks": [
          {
            "type": "command",
            "command": ".claude/hooks/block-dangerous-commands.sh",
            "timeout": 10
          }
        ]
      },
      {
        "matcher": "Edit|Write|MultiEdit",
        "hooks": [
          {
            "type": "command",
            "command": ".claude/hooks/protect-critical-files.sh",
            "timeout": 10
          }
        ]
      }
    ]
  }
}
```

三路 matcher 的分工：

| Matcher | 匹配目标 | 检查内容 |
|---------|---------|---------|
| `Bash` | Shell 命令 | 命令文本中的危险关键词 |
| `mcp__.*` | 所有 MCP 工具 | 工具参数中的危险操作 |
| `Edit\|Write\|MultiEdit` | 文件编辑/写入 | 目标文件是否为关键配置 |

以下脚本依赖 `jq` 解析 JSON 输入。macOS 可通过 `brew install jq` 安装，Linux 用对应包管理器即可。

#### 拦截脚本：block-dangerous-commands.sh

```bash
#!/bin/bash
# .claude/hooks/block-dangerous-commands.sh
# 拦截 Bash 和 MCP 工具中的破坏性命令

INPUT=$(cat)
TOOL_NAME=$(echo "$INPUT" | jq -r '.tool_name')

# 根据工具类型提取要检查的内容
if [ "$TOOL_NAME" = "Bash" ]; then
  CONTENT=$(echo "$INPUT" | jq -r '.tool_input.command // ""')
elif echo "$TOOL_NAME" | grep -q '^mcp__'; then
  # MCP 工具：检查第一层字符串参数值
  # 注意：嵌套 JSON/数组参数不会被检查，需根据具体 MCP 工具扩展深度
  CONTENT=$(echo "$INPUT" | jq -r '[.tool_input | to_entries[].value | select(type == "string")] | join(" ")')
else
  exit 0
fi

# 破坏性命令模式列表
DANGEROUS_PATTERNS=(
  "terraform destroy"
  "terraform apply.*-auto-approve"
  "kubectl delete"
  "DROP TABLE"
  "DROP DATABASE"
  "DROP INDEX"
  "DROP VIEW"
  "TRUNCATE TABLE"
  "TRUNCATE "
  "DELETE FROM"
  "rm -rf /"
  "rm -rf ~"
  "rm -rf \."
  "mkfs\."
  "dd if="
  "> /dev/sd"
  "git push.*--force"
  "git push.*-f "
)

for pattern in "${DANGEROUS_PATTERNS[@]}"; do
  if echo "$CONTENT" | grep -qi "$pattern"; then
    # 使用 JSON 输出，升级到用户手动确认（而非直接拒绝）
    jq -n --arg reason "Dangerous command detected: matches pattern '$pattern'. Please confirm manually." '{
      hookSpecificOutput: {
        hookEventName: "PreToolUse",
        permissionDecision: "ask",
        permissionDecisionReason: $reason
      }
    }'
    exit 0
  fi
done

# 未匹配任何危险模式，放行
exit 0
```

注意这里用的是 `permissionDecision: "ask"` 而不是 `"deny"`——不是直接拒绝，而是升级到用户手动确认。这样不会阻碍正常工作流，但保证了人类必须亲眼看到并确认危险操作。如果你想更严格，可以改为 `"deny"` 直接拒绝。

`permissionDecision` 三种可选值：

| 值 | 行为 |
|----|------|
| `"allow"` | 自动放行，跳过权限确认 |
| `"deny"` | 直接拒绝，向 Claude 反馈原因 |
| `"ask"` | 升级到用户手动确认 |

#### 保护关键文件：protect-critical-files.sh

```bash
#!/bin/bash
# .claude/hooks/protect-critical-files.sh
# 保护关键配置文件不被意外修改

INPUT=$(cat)
FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // ""')

# 受保护的文件模式
PROTECTED_PATTERNS=(
  "*.tfstate"
  "*.tfstate.backup"
  ".env.production"
  "*.pem"
  "*.key"
  "docker-compose.prod*"
)

for pattern in "${PROTECTED_PATTERNS[@]}"; do
  if [[ "$FILE_PATH" == $pattern ]]; then
    jq -n --arg reason "Protected file detected: $FILE_PATH matches '$pattern'. Manual confirmation required." '{
      hookSpecificOutput: {
        hookEventName: "PreToolUse",
        permissionDecision: "ask",
        permissionDecisionReason: $reason
      }
    }'
    exit 0
  fi
done

exit 0
```

如果 Alexey 有这个 Hook，错误四（旧 state 覆盖当前 state）就会被拦截——`.tfstate` 文件的修改需要人工确认。

### 进阶：agent_id 差异化安全策略（2.1.69+）

从 Claude Code 2.1.69 开始，所有 Hook 事件新增了 `agent_id` 和 `agent_type` 字段。这意味着在多 Agent 场景下，你可以为不同 Agent 设置不同的安全策略。

```bash
#!/bin/bash
# 根据 agent_type 应用不同安全策略

INPUT=$(cat)
AGENT_TYPE=$(echo "$INPUT" | jq -r '.agent_type // "main"')
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // ""')

case "$AGENT_TYPE" in
  "code-writer")
    # 写代码的 Agent：允许较宽的 Bash 权限，但仍拦截破坏性命令
    if echo "$COMMAND" | grep -qEi 'rm -rf|DROP TABLE|terraform destroy'; then
      echo "Destructive command blocked for code-writer agent" >&2
      exit 2
    fi
    exit 0
    ;;
  "code-reviewer"|"Explore")
    # 审查/探索 Agent：只允许只读命令
    if echo "$COMMAND" | grep -qE '^(cat|ls|grep|find|git log|git diff|head|tail|wc)'; then
      exit 0
    else
      echo "Reviewer/Explore agent is restricted to read-only commands" >&2
      exit 2
    fi
    ;;
  "main"|*)
    # 主 Agent：标准安全策略
    if echo "$COMMAND" | grep -qEi 'rm -rf|DROP TABLE|terraform destroy'; then
      echo "Destructive command blocked" >&2
      exit 2
    fi
    exit 0
    ;;
esac
```

这在 Agent Teams 场景下尤其有用：reviewer Agent 只有只读权限，即使它被提示注入攻击，也无法执行任何写操作。

### Hook 配置存放位置

| 文件路径 | 作用域 |
|---------|--------|
| `~/.claude/settings.json` | 所有项目（全局） |
| `.claude/settings.json` | 单个项目（可提交到 Git） |
| `.claude/settings.local.json` | 单个项目（加入 gitignore） |
| 托管策略设置 | 组织级（管理员控制） |

团队可以把安全 Hook 放在项目级 `.claude/settings.json` 中提交到仓库，确保所有成员共享同一套安全规则。管理员还可以通过 `allowManagedHooksOnly` 设置，只允许托管策略 Hook 生效，阻止用户自定义 Hook 绕过安全策略。

---

## 六、纵深防御：三道防线如何协同

### 防御矩阵

| 防线 | 层级 | 防御对象 | 实现方式 | 特点 |
|------|------|---------|---------|------|
| 权限模式+规则+沙箱 | 第一道 | 所有工具调用 | 内置配置 | 粗粒度，全局边界 |
| Discernment | 第二道 | 高风险决策 | Prompt 规则 | 语义理解，AI 自主判断 |
| Hook | 第三道（兜底） | 特定危险命令/操作 | 脚本代码 | 硬编码规则，不依赖 AI |

### 设计层级 ≠ 运行时顺序

本文按"粗 → 细 → 兜底"的逻辑讲解三道防线，这是**设计层级**——帮你理解安全体系的架构。但 Claude Code 的**运行时实际顺序**不同：

```
用户输入任务
  ↓
[Discernment 在决策阶段介入]  ← Claude 读到规则文件中的触发条件
  ↓                             如果命中高风险 → 风险评估 → 用户确认
Claude 决定调用工具
  ↓
[PreToolUse Hook 执行]         ← 硬编码规则拦截，先于权限弹窗
  ↓
[权限检查（Permission Check）]  ← 内置权限模式判定
  ↓
工具实际执行
  ↓
[PostToolUse Hook 执行]         ← 审计日志记录
```

几个关键区分：
- **Discernment** 不是 Claude Code 内置机制，是通过规则文件注入的 prompt 级行为，发生在 Claude 的决策阶段——工具调用之前
- **PreToolUse Hook** 在运行时先于权限弹窗执行
- 三者的执行时机不同，但在安全设计中各有分工

### 实际工作流示例

用户说："帮我清理测试环境的旧数据。"

1. **Discernment 在决策阶段介入**：Claude 读到规则文件中的触发条件，命中"删数据"。触发审查。
2. Claude 输出风险评估：
   - 失败 Top3：误删生产数据、清理范围过大、无备份可回滚
   - 关键假设："测试环境"——来源：用户口头描述，未验证连接串
   - 最小替代：先 `SELECT COUNT(*)` 确认数据量，用 `TRUNCATE` 而非 `DROP`
3. 用户确认方案后，Claude 生成 `DROP TABLE old_data` 命令。
4. **PreToolUse Hook 兜底拦截**：命中 `DROP TABLE` 模式 → 升级到用户手动确认。
5. 用户看到弹窗，确认执行。
6. **PostToolUse Hook** 记录审计日志。

为什么这个体系有效？

- **Discernment 在任务层面拦截**——可能直接改变方案（如改用 `TRUNCATE`、先备份）
- **Hook 在命令层面拦截**——即使 Discernment 漏了（AI 误判、提示注入），危险命令也跑不掉
- 两者**互补，不是替代关系**

---

## 七、我的安全配置实战分享

### 完整配置全貌

**CLAUDE.md 中的安全相关配置：**

```markdown
## Discernment 门禁
- 高风险任务（不可逆、安全、数据正确性、架构选型）执行前，须走 Discernment 审查
- 详细规则 → rules/discernment.md
- 用户可标注 `risk=low` 跳过 / `risk=high` 强制触发
```

**settings.json 中的安全 Hook 配置：**

```json
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": ".claude/hooks/block-dangerous-commands.sh",
            "timeout": 10
          }
        ]
      },
      {
        "matcher": "mcp__.*",
        "hooks": [
          {
            "type": "command",
            "command": ".claude/hooks/block-dangerous-commands.sh",
            "timeout": 10
          }
        ]
      },
      {
        "matcher": "Edit|Write|MultiEdit",
        "hooks": [
          {
            "type": "command",
            "command": ".claude/hooks/protect-critical-files.sh",
            "timeout": 10
          }
        ]
      }
    ]
  }
}
```

三路 matcher 各司其职：Bash 和 MCP 工具走 `block-dangerous-commands.sh` 检查破坏性命令关键词，文件编辑走 `protect-critical-files.sh` 保护关键配置文件。这两个脚本的完整代码在第五章，经过实际测试验证可用。

### 踩过的坑

**坑一：Dangerous 模式下 Hook 也能拦。** 这其实是好事——Hook 是最后的安全网。但很多人不知道这一点，以为开了 `bypassPermissions` 就万事大吉。事实上，Hook 的执行不受权限模式影响。

**坑二：Hook 超时设置太短会跳过检查。** `command` 类型的默认超时是 600 秒，但如果你手动设了一个很短的超时（比如 1 秒），在网络延迟或系统负载高时，Hook 可能因为超时而被跳过。超时失败是**非阻断**错误——Hook 不执行，但工具调用继续。建议至少给 5-10 秒。

**坑三：多 Hook 的执行顺序。** 同一个事件可以配置多个 matcher 组，它们按配置顺序依次执行。如果第一个 Hook 返回 `deny`，后续 Hook 不会执行。设计多个 Hook 时要注意优先级。

### 对 Alexey 案例的总结

五个错误环环相扣，`bypassPermissions` 是放大器而非唯一根因。完整归因：

**基础设施层的错误：**
1. 共用 Terraform 配置——新旧基础设施混在一起
2. State 文件绑定单机——换电脑后 state 丢失
3. 无 `deletion_protection`（AWS RDS 层）/ 无 `prevent_destroy`（Terraform 层）
4. 无独立备份——RDS 快照随基础设施一并销毁

**Claude Code 层的错误：**
5. 用了 Dangerous 模式——所有权限检查被跳过
6. 无 Discernment 风险评估——AI 直接从"清理重复资源"滑坡到 `terraform destroy`
7. 无 Hook 兜底拦截——`terraform destroy` 畅通无阻，`.tfstate` 文件被覆盖也无人察觉

**核心教训：即使有三道 Claude 防线，基础设施层的防护（删除保护、独立备份、账户隔离）同样不可或缺。** 安全是一个系统工程，不能只靠工具。

---

## 八、结语：给 AI 的权力越大，安全网要越密

Anthropic 2026 Agentic Coding Trends Report 指出，Agent 的任务范围正从分钟级扩展到天级甚至周级，多 Agent 协调、后台执行、并行任务已成为标配。

> "Perhaps the most valuable capability developments in 2026 will be agents learning when to ask for help, rather than blindly attempting every task." —— Anthropic 2026 Report

但行业的安全准备远远跟不上：Cisco 调查显示，计划部署 Agent AI 的组织中，**仅 29% 表示已做好安全准备，准备度缺口达 71%**。（来源：[Cisco State of AI Security 2026](https://www.helpnetsecurity.com/2026/03/03/enterprise-ai-agent-security-2026/)）McKinsey 的建议是："Design for trust first, speed second. Start with bounded autonomy."

Anthropic 自己也在推进安全机制：2.1.69 版本新增的 `agent_id` 字段让多 Agent 场景下的差异化安全策略成为可能；`allowManagedHooksOnly` 让组织可以统一管理安全策略；`InstructionsLoaded` 事件支持审计哪些指令文件被加载。

### 行动清单

**Claude Code 层（立即可做）：**

1. **检查你的权限模式。** 至少用 `acceptEdits`，别用 `bypassPermissions`（除非在隔离容器里）。在 `settings.json` 里加一行：
   ```json
   { "defaultMode": "acceptEdits" }
   ```

2. **加一个 PreToolUse Hook 拦截高危命令。** 最小可用配置，复制即用——把上面第五章的 `block-dangerous-commands.sh` 脚本放到 `.claude/hooks/` 目录，然后在 `settings.json` 的 hooks 配置中加上 Bash 和 MCP 的 matcher。

3. **在 CLAUDE.md 或 rules/ 里加一段 Discernment 规则。** 复制第四章的完整规则文件到 `~/.claude/rules/discernment.md`，在 CLAUDE.md 中加一行引用。

**基础设施层（对生产环境）：**

4. **给生产数据库开 `deletion_protection`。** AWS RDS 一行配置：
   ```hcl
   resource "aws_db_instance" "production" {
     deletion_protection = true
   }
   ```
   Terraform 层加 `prevent_destroy`：
   ```hcl
   lifecycle {
     prevent_destroy = true
   }
   ```

5. **State 文件迁到远程存储。** S3 + DynamoDB 锁，不要留在本地：
   ```hcl
   terraform {
     backend "s3" {
       bucket         = "my-terraform-state"
       key            = "prod/terraform.tfstate"
       region         = "us-east-1"
       dynamodb_table = "terraform-locks"
     }
   }
   ```

**备份层（最后一道保险）：**

6. **确保备份独立于基础设施。** 备份不能随 `terraform destroy` 一起删。用独立的 S3 存储桶，启用版本控制。

7. **（进阶）自动化恢复验证。** Alexey 事后实施的方案：每日凌晨从备份创建新 DB 实例 → Lambda 运行验证查询（如 `SELECT COUNT(*) FROM email`）→ 验证通过后停止实例 → 只付存储费。正如 Alexey 所说："I want to continuously test that backups can actually be restored."

---

**参考来源：**

- Alexey Grigorev 案例原文：[How I Dropped Our Production Database and Now Pay 10% More for AWS](https://alexeyondata.substack.com/p/how-i-dropped-our-production-database)
- Veracode 数据：[2025 GenAI Code Security Report](https://www.veracode.com/resources/analyst-reports/2025-genai-code-security-report/)
- Anthropic 趋势报告：[2026 Agentic Coding Trends Report](https://resources.anthropic.com/2026-agentic-coding-trends-report)
- Google Antigravity 事故：[Tom's Hardware](https://www.tomshardware.com/tech-industry/artificial-intelligence/googles-agentic-ai-wipes-users-entire-hard-drive-without-permission-after-misinterpreting-instructions-to-clear-a-cache-i-am-deeply-deeply-sorry-this-is-a-critical-failure-on-my-part)
- Replit 事故：[Fortune](https://fortune.com/2025/07/23/ai-coding-tool-replit-wiped-database-called-it-a-catastrophic-failure/)
- Cisco 安全准备度数据：[Help Net Security](https://www.helpnetsecurity.com/2026/03/03/enterprise-ai-agent-security-2026/)
- MCP 安全漏洞研究：[MCP Landscape and Security Threats](https://xinyi-hou.github.io/files/hou2025mcp.pdf)

---

## 相关阅读

- [Claude Code 完整安装与配置教程（支持国内模型）](/posts/claude-code-installation/) — 从零开始安装 Claude Code，本文假设你已完成基础配置
- [我如何使用 Claude Code：先计划，再编码](/posts/claude-code-plan-before-code/) — 安全的前提是有好的工作流，先计划再执行能大幅降低风险
- [Claude Code 调用国内模型的缓存大坑](/posts/claude-code-cache-pitfall/) — 另一个避坑实战，与本文形成"避坑系列"
- [同样的话跟 Claude Code 说了八遍，是时候让它自己记住了](/posts/claude-code-memory-rules/) — Discernment 规则文件的基础——如何让 Claude 记住你的规则
- [MCP 生态实战：补齐 Claude Code 的 UI 短板](/posts/mcp-stitch-ui-design/) — MCP 安全风险的实战案例，与本文的安全防线形成互补
