Tips & Tricks (更新: 2026/6/3)

Claude Code 安全失败案例7个: 原因、恢复与预防

从.env泄漏、生产数据库误删、CI费用暴涨等案例,学习Claude Code安全防护。

Claude Code 安全失败案例7个: 原因、恢复与预防

Claude Code 不只是一个会回答问题的聊天窗口。它可以修改文件、运行测试、读取 Git 状态,甚至建议部署命令。能力越强,误操作的速度也越快。如果开发者在疲劳状态下连续批准权限提示,本来需要手工输入的危险命令,可能几秒钟内就被执行。

这篇文章把 Claude Code 常见安全事故拆成7类,并给出可以直接复制使用的配置。对初学者来说,permission 是“允许代理做什么”的边界,hook 是“工具执行前后的检查点”,sandbox 是“即使出错也能缩小影响范围的隔离工作间”。下面的 settings.json、Node.js 检查脚本和 GitHub Actions 配置,都以可落地为目标。

flowchart TD
  Request["User request"] --> Plan["Claude Code plan"]
  Plan --> Permission["Permission rules"]
  Permission --> Hook["PreToolUse hook"]
  Hook --> Execute["Tool execution"]
  Execute --> Audit["Log, review, recovery"]
  Hook -->|block risky command| Stop["Stop before damage"]

先看失败地图

失败案例常见触发点影响先安装的护栏
提交 .env“CI也需要这个文件,顺手提交吧”API key 泄漏、被盗刷.gitignore 和 staged 文件扫描
删除生产数据migration 连到错误数据库数据丢失、恢复成本高执行DB命令前检查环境名
git push --force急着解决冲突覆盖团队成员提交ask 规则和分支保护
CI里的AI review循环每个PR都触发大范围自动化Actions分钟数和API费用上涨max-turns、timeout、最小权限
粘贴不可信日志日志里混入隐藏指令prompt injection默认拒绝高风险Web和Shell获取
MCP权限过宽轻易信任外部服务器本地数据被过度读取只允许可信MCP服务器
批准疲劳用户一路点同意危险操作被放行用hook自动失败关闭

重点不是说 Claude Code 默认不安全。官方 Security 文档说明了只读默认权限、权限提示、沙箱和用户责任。真正的风险在于团队流程变忙后,人会跳过检查。所以安全设置要让正确动作更顺手,让危险动作必须停下来。

用例1: 阻止个人项目泄漏API key

初学者最容易误解 .env。它不是保险箱,只是一个本地文本文件。只有在它不进入 Git、不出现在日志、不被截图、不被复制到 prompt 的前提下才相对安全。Stripe、SendGrid、Anthropic、GitHub token 一旦进入公开仓库,就要按已泄漏处理。

仓库里只提交变量的形状,不提交真实值。

# .gitignore
.env
.env.*
!.env.example
secrets/
*.pem
*.key
*service-account*.json
credentials.json
# .env.example
ANTHROPIC_API_KEY=replace_me
DATABASE_URL=postgres://app_user:password@localhost:5432/app_dev
STRIPE_SECRET_KEY=sk_test_replace_me

接着收紧 Claude Code 权限。deny 是拒绝,ask 是每次确认,allow 是对低风险命令自动放行。官方 SettingsConfigure permissions 页面解释了这些规则如何被评估。

{
  "$schema": "https://json.schemastore.org/claude-code-settings.json",
  "permissions": {
    "allow": [
      "Bash(npm run lint)",
      "Bash(npm run test *)",
      "Bash(git status)",
      "Bash(git diff *)"
    ],
    "ask": [
      "Bash(git push *)",
      "Bash(npm run deploy *)",
      "Write(./migrations/**)"
    ],
    "deny": [
      "Read(./.env)",
      "Read(./.env.*)",
      "Read(./secrets/**)",
      "Bash(rm -rf *)",
      "Bash(curl *)",
      "Bash(wget *)",
      "WebFetch"
    ]
  }
}

这不是把 Claude Code 关起来,而是把安全的日常动作变快,把破坏性动作变慢。如果项目确实需要访问网页或外部API,不要一开始全开。先写清楚用途、允许的域名和审核步骤,再逐步放宽。

用例2: 团队PR review不要变成形式主义

团队里更危险的事故往往不是 Claude Code 写错代码,而是流程变松。大家看到“AI已经review过”就不再看权限文件、workflow变更、credential处理。这些地方恰好最容易漏掉安全问题。

下面的脚本没有第三方依赖。默认扫描 staged 文件,在CI里可以用 --all 扫描整个仓库。

// scripts/claude-security-check.mjs
import { execFileSync } from "node:child_process";
import fs from "node:fs";

const args = process.argv.slice(2);
const scanAll = args.includes("--all");
const explicitFiles = args.filter((arg) => arg !== "--all");

function runGit(args) {
  return execFileSync("git", args, { encoding: "utf8", maxBuffer: 10 * 1024 * 1024 });
}

function filesToScan() {
  if (explicitFiles.length > 0) return explicitFiles;
  if (scanAll) return runGit(["ls-files"]).split(/\r?\n/).filter(Boolean);
  return runGit(["diff", "--cached", "--name-only"]).split(/\r?\n/).filter(Boolean);
}

function readTrackedOrWorkingTree(file) {
  if (scanAll || explicitFiles.length > 0) return fs.readFileSync(file, "utf8");
  return runGit(["show", `:${file}`]);
}

const forbiddenPath = [
  /^\.env$/,
  /^\.env\./,
  /(^|\/)secrets\//,
  /(^|\/).*service-account.*\.json$/i,
  /(^|\/)credentials\.json$/i,
  /\.(pem|key)$/i
];

const secretPattern =
  /(sk-ant-[A-Za-z0-9_-]{20,}|sk_live_[A-Za-z0-9_-]{20,}|AKIA[0-9A-Z]{16}|-----BEGIN (?:RSA |EC |OPENSSH )?PRIVATE KEY-----)/;

let failed = false;

for (const file of filesToScan()) {
  if (forbiddenPath.some((pattern) => pattern.test(file))) {
    console.error(`[blocked] forbidden secret path: ${file}`);
    failed = true;
    continue;
  }

  try {
    const text = readTrackedOrWorkingTree(file);
    if (secretPattern.test(text)) {
      console.error(`[blocked] secret-like value found in: ${file}`);
      failed = true;
    }
  } catch {
    // Ignore deleted or binary files.
  }
}

if (failed) process.exit(1);
console.log("security check passed");
{
  "scripts": {
    "security:staged": "node scripts/claude-security-check.mjs",
    "security:all": "node scripts/claude-security-check.mjs --all"
  }
}

这里的坑是“有脚本就算完成”。要把 npm run security:staged 放进提交前流程、PR模板或CI。提示 Claude Code “记得运行安全检查”不够可靠,自动失败才可靠。

用例3: 保护生产数据库和CI预算

生产事故通常来自环境混淆。DROP TABLE 不是全部问题,真正的问题是以为自己连的是开发库,实际连到了生产 DATABASE_URL。让 Claude Code 删除旧数据之前,先用人能读懂的形式显示数据库标签、云项目、分支名和备份时间点。

如果在 GitHub Actions 中使用 Claude Code,官方 GitHub Actions 文档建议把API key放在Secrets里,并限制到必要权限。下面的workflow只做PR差异review,不给仓库写权限。

name: Claude Code guarded review

"on":
  pull_request:
    types: [opened, synchronize, reopened]

permissions:
  contents: read
  pull-requests: write

jobs:
  claude-security-review:
    runs-on: ubuntu-latest
    timeout-minutes: 15
    steps:
      - uses: actions/checkout@v4
        with:
          persist-credentials: false

      - name: Run repository secret scan
        run: node scripts/claude-security-check.mjs --all

      - uses: anthropics/claude-code-action@v1
        with:
          anthropic_api_key: "${{ secrets.ANTHROPIC_API_KEY }}"
          prompt: >
            Review only the pull request diff for secret handling, auth checks,
            destructive commands, and permission changes. Do not modify files.
          claude_args: |
            --max-turns 3
            --disallowedTools "Bash(git push *)" "Bash(npm run deploy *)" "Bash(rm -rf *)"

permissions: contents: read 很重要,因为只做review的job不需要写仓库。timeout-minutes--max-turns 也属于安全控制,因为失控的自动化会造成费用和可用性事故。

已经出事时的恢复顺序

API key 泄漏时,不要先清理 Git 历史。第一步是到提供商后台撤销或轮换密钥。仓库变干净并不能阻止已经复制到外部的旧值继续被使用。

  1. 撤销或轮换泄漏的key。
  2. 查看暴露窗口内的使用日志和账单。
  3. 替换 GitHub Secrets、部署平台变量和CI变量。
  4. 从 Git 历史中移除值,必要时请求缓存清理。
  5. 在同一个修复PR中加入 .gitignore、权限设置和扫描脚本。

如果生产数据已经受损,先暂停写入或切到只读,再考虑恢复。先决定备份时间点、恢复目标和可接受的数据丢失窗口。恢复命令必须一条一条执行,并保留日志。

官方文档、内部链接和下一步

建议把官方 SecurityConfigure permissionsSettingsHooksGitHub Actions 作为事实来源。hooks 尤其值得团队提前理解,因为它能在工具执行之前运行自定义检查。

站内可以继续阅读 /zh/blog/claude-code-security-best-practices//zh/blog/claude-code-permissions-guide//zh/blog/claude-code-secrets-management/,把事故、权限和密钥管理连成一套流程。

如果需要现成模板,可以从 /products/ 里的设置指南和检查表开始。团队要把它落到导入计划、CI策略和review流程时,可以使用 /training/ 的咨询与培训入口。

在 Masa 的本地测试仓库中,这套设置在发布前拦住了误提交 .env、假的 sk_live_ 字符串,以及权限过宽的 GitHub Actions review job。不过正则扫描无法识别所有未知key格式,所以长期方案必须分层:服务端轮换、最小权限、自动检查,以及批准 Claude Code 操作前的人工复核。

#claude-code #security #incident #best-practices #devops
免费

免费 PDF: Claude Code 速查表

输入邮箱即可获取一页 PDF,整理常用命令、审查习惯和安全工作流。

我们会妥善保护你的信息,不发送垃圾邮件。

把 Claude Code 变成真正能带来结果的工作流

先领取中文说明的免费 PDF,再进入英文商品页选择合适的教材。如果你需要团队落地、流程设计或内容变现支持,也可以直接咨询。

Masa

关于作者

Masa

专注 Claude Code 实务流程、团队导入和内容转化的工程师。