Claude Code 安全失败案例7个: 原因、恢复与预防
从.env泄漏、生产数据库误删、CI费用暴涨等案例,学习Claude Code安全防护。
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 是对低风险命令自动放行。官方 Settings 和 Configure 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 历史。第一步是到提供商后台撤销或轮换密钥。仓库变干净并不能阻止已经复制到外部的旧值继续被使用。
- 撤销或轮换泄漏的key。
- 查看暴露窗口内的使用日志和账单。
- 替换 GitHub Secrets、部署平台变量和CI变量。
- 从 Git 历史中移除值,必要时请求缓存清理。
- 在同一个修复PR中加入
.gitignore、权限设置和扫描脚本。
如果生产数据已经受损,先暂停写入或切到只读,再考虑恢复。先决定备份时间点、恢复目标和可接受的数据丢失窗口。恢复命令必须一条一条执行,并保留日志。
官方文档、内部链接和下一步
建议把官方 Security、Configure permissions、Settings、Hooks、GitHub 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 操作前的人工复核。
免费 PDF: Claude Code 速查表
输入邮箱即可获取一页 PDF,整理常用命令、审查习惯和安全工作流。
我们会妥善保护你的信息,不发送垃圾邮件。
把 Claude Code 变成真正能带来结果的工作流
先领取中文说明的免费 PDF,再进入英文商品页选择合适的教材。如果你需要团队落地、流程设计或内容变现支持,也可以直接咨询。
关于作者
Masa
专注 Claude Code 实务流程、团队导入和内容转化的工程师。
相关文章
Claude Code权限安全阶梯:逐步放开访问而不失控
从只读到有限编辑、验证命令和部署检查的 Claude Code 权限升级流程。
Claude Code 小PR证据包:让小改动真正可审查
用差异、验证命令、公开URL、CTA路径和回滚说明,把Claude Code的小PR变得可审查。
Claude Code 提交前 Review Gate:同时检查差异、测试、公开 URL 和 CTA
提交前用 Claude Code 审查差异范围、build、公开 URL、Gumroad 链接、咨询 CTA、缺少测试和无关文件。