安全最佳实践

全面掌握 Claude Code 的安全机制 — 权限控制、敏感文件保护、命令拦截、API Key 管理

安全最佳实践

Claude Code 是一个强大的 AI 编程助手,但"强大"也意味着它需要较高的系统权限 — 读写文件、执行命令、访问网络。这就像给一个实习生配了管理员账号:能力很强,但必须有合适的安全边界。

这篇文档将帮助你建立全面的安全防线,从个人使用到团队协作,从开发环境到 CI/CD 自动化,确保你在享受 AI 编程效率的同时,不会踩到安全的坑。

理解 Claude Code 的安全模型

Claude Code 在你的终端中运行

这一点至关重要,也是理解所有安全措施的基础:Claude Code 不是运行在云端的沙箱里,而是直接运行在你的本地终端中

这意味着:

  • 它能读取你机器上的任何文件(只要你的用户有权限)
  • 它能执行任何 Shell 命令
  • 它能访问你的环境变量(包括里面可能存在的密钥)
  • 它能通过网络发送和接收数据

当然,Claude Code 有内置的安全机制来约束这些能力。但你应该始终记住这个基本事实:它的权限上限就是你的用户权限。

权限审批机制

Claude Code 的核心安全理念是人在回路中(Human in the Loop)。默认情况下,它在执行以下操作时会请求你的确认:

  • 第一次使用某个工具
  • 执行 Shell 命令(特别是你没有预先批准的)
  • 写入新文件或修改现有文件
  • 访问网络资源

你看到的权限请求大致是这样的:

Claude wants to run: rm -rf node_modules && npm install

Allow?
  (y) Yes, allow once
  (a) Always allow "npm install" commands
  (n) No, deny

关键原则:如果你不确定某个操作是否安全,选"No"。你总是可以在了解清楚后再批准。

三道防线

Claude Code 的安全体系由三道防线组成:

第一道:权限模式(全局策略)
  ↓
第二道:Allow/Deny 规则(精细控制)
  ↓
第三道:Hooks(自定义拦截逻辑)

下面我们逐一展开。

权限配置

四种权限模式对比

Claude Code 提供四种权限模式,安全级别从高到低排列:

模式 文件编辑 命令执行 适用场景 安全级别
plan 禁止 禁止(仅只读) 代码审查、架构分析 最高
default 首次询问 每次询问 日常开发
acceptEdits 自动批准 每次询问 频繁修改文件的任务
bypassPermissions 自动批准 自动批准 CI/CD、受信任环境

各模式详解:

plan 模式:Claude 只能搜索和阅读代码,不能做任何修改。适合你想让 Claude 分析代码但不希望它动任何东西的场景。通过 Shift+Tab 切换到此模式。

default 模式:推荐的日常模式。Claude 第一次使用某类工具时会询问,你批准后同类操作不再重复询问。Shell 命令每次都会询问。

acceptEdits 模式:信任 Claude 的文件编辑能力,但对命令执行保持警惕。适合你需要 Claude 大量修改代码文件,但不希望它随意执行命令的场景。

bypassPermissions 模式:跳过所有权限检查。只在你完全信任当前任务、或者在隔离的 CI/CD 环境中使用。

通过 /permissions 查看和修改

在 Claude Code 中随时输入 /permissions 可以查看当前的权限状态:

/permissions

输出会显示当前模式、已批准的工具、Allow/Deny 规则等。

settings.json 中的权限配置

权限配置存储在 settings.json 中,分为两个级别:

用户级(影响所有项目):~/.claude/settings.json 项目级(仅影响当前项目):.claude/settings.json

{
  "permissions": {
    "defaultMode": "default",
    "allow": [
      "Bash(npm run lint)",
      "Bash(npm run test:*)",
      "Bash(git status)",
      "Bash(git add:*)",
      "Bash(git diff:*)",
      "Bash(git log:*)",
      "Bash(node:*)",
      "Bash(python:*)"
    ],
    "deny": [
      "Bash(rm -rf:*)",
      "Bash(git push --force:*)",
      "Bash(curl:*)",
      "Bash(wget:*)",
      "Read(.env)",
      "Read(.env.*)",
      "Read(secrets/**)"
    ]
  }
}

规则语法说明:

语法 含义 示例
Bash(cmd) 精确匹配命令 Bash(npm run lint)
Bash(cmd:*) 匹配命令前缀 Bash(git log:*) 匹配所有 git log 开头的命令
Read(path) 匹配文件读取 Read(.env)
Write(path) 匹配文件写入 Write(src/**)
** 多层目录通配 Read(secrets/**) 匹配 secrets 下所有层级的文件
* 单层通配 Read(.env.*) 匹配 .env.local、.env.production 等

重要:Deny 规则的优先级高于 Allow 规则。即使你在 Allow 中批准了某个操作,如果它同时匹配了 Deny 规则,仍然会被拒绝。

敏感文件保护

使用 .claudeignore 排除敏感目录

.claudeignore 文件的语法与 .gitignore 相同,被列入的文件和目录对 Claude Code 完全不可见:

在项目根目录创建 .claudeignore

# 环境变量和密钥
.env
.env.*
secrets/
*.pem
*.key
*credentials*

# 敏感配置
config/production.yml
config/secrets.yml

# 个人数据
data/users/
*.sqlite
*.db

# 其他敏感目录
.aws/
.ssh/
.gnupg/

注意.claudeignore 让 Claude 完全看不到这些文件 — 它甚至不知道这些文件存在。这比 Deny 规则更彻底。

使用 Hooks 拦截对敏感文件的修改

如果你希望 Claude 能读取某些文件但不能修改,可以用 Hooks 来实现精细控制:

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Write|Edit",
        "hooks": [
          {
            "type": "command",
            "command": "python3 -c \"\nimport sys, json, os\ntool_input = json.loads(os.environ.get('TOOL_INPUT', '{}'))\npath = tool_input.get('file_path', '') or tool_input.get('path', '')\nprotected = ['.env', 'credentials', 'secret', '.pem', '.key']\nfor p in protected:\n    if p in path.lower():\n        print(f'BLOCKED: 不允许修改包含 {p} 的文件', file=sys.stderr)\n        sys.exit(2)\n\""
          }
        ]
      }
    ]
  }
}

这个 Hook 会在 Claude 尝试写入或编辑文件之前检查文件路径,如果路径中包含敏感关键词,就阻止操作(exit code 2 表示阻断)。

保护配置模板

对于团队项目,建议创建一个标准的安全配置文件,存放在仓库中:

// .claude/settings.json(提交到 Git)
{
  "permissions": {
    "deny": [
      "Read(.env)",
      "Read(.env.*)",
      "Read(secrets/**)",
      "Read(**/*.pem)",
      "Read(**/*.key)",
      "Write(.git/**)",
      "Bash(rm -rf:*)",
      "Bash(git push --force:*)",
      "Bash(git reset --hard:*)",
      "Bash(chmod 777:*)",
      "Bash(curl|wget:*)"
    ]
  },
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "echo \"$TOOL_INPUT\" | python3 -c \"import sys,json; cmd=json.load(sys.stdin).get('command',''); blocked=['DROP TABLE','DELETE FROM','TRUNCATE','password','token','secret']; [sys.exit(2) for b in blocked if b.lower() in cmd.lower()]\""
          }
        ]
      }
    ]
  }
}

命令执行安全

理解 Bash 工具的行为

Claude Code 通过 Bash 工具执行 Shell 命令。默认情况下,除了你预先批准的命令外,每次执行都需要你确认。

一些需要注意的行为:

  • 命令在你当前的 Shell 环境中执行
  • 环境变量对命令可见
  • 命令可以修改文件系统
  • 命令可以安装软件
  • 命令可以访问网络

哪些命令会被自动审批

当你在 settings.jsonallow 列表中添加了某个命令模式后,匹配的命令会自动执行,不再询问。

建议预批准的安全命令:

{
  "permissions": {
    "allow": [
      "Bash(git status)",
      "Bash(git diff:*)",
      "Bash(git log:*)",
      "Bash(git branch:*)",
      "Bash(ls:*)",
      "Bash(cat:*)",
      "Bash(head:*)",
      "Bash(tail:*)",
      "Bash(wc:*)",
      "Bash(find:*)",
      "Bash(grep:*)",
      "Bash(npm run lint:*)",
      "Bash(npm run test:*)",
      "Bash(python -m pytest:*)"
    ]
  }
}

危险命令拦截

以下命令应该始终放在 Deny 列表中,永远不允许自动执行:

{
  "permissions": {
    "deny": [
      "Bash(rm -rf:*)",
      "Bash(rm -r /:*)",
      "Bash(git push --force:*)",
      "Bash(git push -f:*)",
      "Bash(git reset --hard:*)",
      "Bash(git checkout -- .:*)",
      "Bash(git clean -f:*)",
      "Bash(chmod 777:*)",
      "Bash(chown:*)",
      "Bash(dd:*)",
      "Bash(mkfs:*)",
      "Bash(shutdown:*)",
      "Bash(reboot:*)"
    ]
  }
}

通过 Hooks 自定义命令拦截

对于更复杂的拦截逻辑,使用 Hooks:

示例 1:阻止所有网络请求命令

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "echo \"$TOOL_INPUT\" | python3 -c \"\nimport sys, json\ncmd = json.load(sys.stdin).get('command', '')\nnet_cmds = ['curl', 'wget', 'nc ', 'netcat', 'ssh ', 'scp ', 'rsync']\nfor nc in net_cmds:\n    if nc in cmd:\n        print(f'BLOCKED: 不允许执行网络命令 ({nc})', file=sys.stderr)\n        sys.exit(2)\n\""
          }
        ]
      }
    ]
  }
}

示例 2:记录所有命令到审计日志

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "echo \"$(date '+%Y-%m-%d %H:%M:%S') [Bash] $TOOL_INPUT\" >> ~/.claude/audit.log"
          }
        ]
      }
    ],
    "PostToolUse": [
      {
        "matcher": "Write|Edit",
        "hooks": [
          {
            "type": "command",
            "command": "echo \"$(date '+%Y-%m-%d %H:%M:%S') [FileChange] $TOOL_INPUT\" >> ~/.claude/audit.log"
          }
        ]
      }
    ]
  }
}

这样你就有了一份完整的操作审计日志,可以随时回溯 Claude Code 做了什么。

API Key 安全

不要在 CLAUDE.md 中硬编码 API Key

这是最常见的安全错误。CLAUDE.md 文件通常会提交到 Git 仓库,而且 Claude Code 在每次启动时都会读取它。如果里面包含 API Key,那么:

  1. Key 会被提交到 Git 历史中(即使后来删除了)
  2. Key 对 Claude Code 可见,可能出现在日志或分析结果中
  3. 团队其他成员都能看到这个 Key

错误做法:

<!-- CLAUDE.md -->
## API 配置
数据库连接:postgresql://admin:P@ssw0rd@localhost:5432/mydb
OpenAI Key:sk-xxxxxxxxxxxxxxxxxxxx

正确做法:

<!-- CLAUDE.md -->
## API 配置

- 数据库连接和 API Key 通过 .env 文件管理
- .env 文件不提交到 Git(已在 .gitignore 中)
- 新开发者需要复制 .env.example 并填入自己的凭据

使用环境变量管理密钥

推荐的密钥管理方式:

# .env(不提交到 Git)
DATABASE_URL=postgresql://admin:P@ssw0rd@localhost:5432/mydb
OPENAI_API_KEY=sk-xxxxxxxxxxxxxxxxxxxx
REDIS_URL=redis://localhost:6379

# .env.example(提交到 Git,不含实际值)
DATABASE_URL=postgresql://user:password@localhost:5432/dbname
OPENAI_API_KEY=sk-your-key-here
REDIS_URL=redis://localhost:6379

确保 .env.gitignore.claudeignore 中:

# .gitignore
.env
.env.local
.env.production

# .claudeignore(如果你不希望 Claude 读取 .env)
.env
.env.*

API Key 泄露后的处理步骤

如果你怀疑 API Key 已经泄露(比如不小心提交到了 Git),请立即执行以下步骤:

1. 立即轮换密钥

   - 到对应服务的控制台生成新的 API Key
   - 更新所有使用该 Key 的环境变量

2.  Git 历史中移除
   git filter-branch --force --index-filter \
     "git rm --cached --ignore-unmatch .env" \
     --prune-empty --tag-name-filter cat -- --all

   或使用更安全的 BFG Repo-Cleaner
   bfg --delete-files .env
   git reflog expire --expire=now --all
   git gc --prune=now --aggressive

3. 强制推送清理后的历史
   git push --force --all

4. 检查异常使用

   - 查看 API 使用日志检查是否有异常调用
   - 检查计费记录看是否有异常消费

5. 通知团队

   - 告知所有开发者重新克隆仓库
   - 更新所有部署环境的密钥

团队安全规范

共享 settings.json 模板

为团队创建统一的安全基线配置,提交到项目仓库的 .claude/settings.json

{
  "permissions": {
    "defaultMode": "default",
    "allow": [
      "Bash(npm run:*)",
      "Bash(git status)",
      "Bash(git diff:*)",
      "Bash(git log:*)",
      "Bash(python -m pytest:*)"
    ],
    "deny": [
      "Read(.env)",
      "Read(.env.*)",
      "Read(secrets/**)",
      "Read(**/*.pem)",
      "Read(**/*.key)",
      "Read(**/*credential*)",
      "Write(.git/**)",
      "Bash(rm -rf:*)",
      "Bash(git push --force:*)",
      "Bash(git reset --hard:*)",
      "Bash(curl:*)",
      "Bash(wget:*)",
      "Bash(ssh:*)",
      "Bash(scp:*)"
    ]
  },
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "echo \"$(date -Iseconds) TOOL_USE: $TOOL_INPUT\" >> .claude/audit.log"
          }
        ]
      }
    ]
  }
}

团队成员可以在 ~/.claude/settings.json(用户级)中添加个人配置,但项目级的 Deny 规则不可被覆盖。

CI/CD 中的安全配置

在 CI/CD 环境中使用 Claude Code(Headless 模式)时,安全配置更为重要:

# GitHub Actions 示例
name: AI Code Review
on: [pull_request]

jobs:
  review:
    runs-on: ubuntu-latest
    steps:

      - uses: actions/checkout@v4

      - name: Run Claude Code Review
        env:
          ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
        run: |
          claude --print --dangerously-skip-permissions \
            "请审查本次 PR 的代码变更,给出安全性和代码质量的评价" \
            < /dev/null

CI/CD 安全注意事项:

注意项 说明
API Key 管理 使用 CI/CD 平台的 Secrets 管理(如 GitHub Secrets),不要硬编码
权限最小化 CI 环境中的 Claude Code 应该只有只读权限,不应修改代码
网络隔离 限制 CI 环境的出站网络访问
超时设置 设置合理的执行时间上限,防止异常长时间运行
日志清理 确保 CI 日志中不包含敏感信息

Headless 模式安全注意事项

Headless 模式(--print-p)用于非交互式场景,没有人在回路中确认操作。使用时需要格外注意:

# 安全的 Headless 用法 — 只读操作
claude --print "分析 src/ 目录的代码结构"

# 需要写操作时,限定具体文件
claude --print "修复 src/utils.py 中的类型错误"

# 使用 --dangerously-skip-permissions 时要明确知道风险
claude --print --dangerously-skip-permissions "运行 npm test"

--dangerously-skip-permissions 这个参数名字之所以这么长,就是为了提醒你:跳过权限检查是危险的。只在你完全控制输入提示词、完全了解可能的操作时才使用。

企业级安全

网络访问控制

如果你的企业有严格的网络安全策略,可以通过以下方式控制 Claude Code 的网络访问:

1. 代理配置

通过环境变量设置 HTTP 代理,所有网络请求都经过代理,方便审计和控制:

# 在 .bashrc 或 .zshrc 中设置
export HTTP_PROXY=http://proxy.company.com:8080
export HTTPS_PROXY=http://proxy.company.com:8080
export NO_PROXY=localhost,127.0.0.1,.company.com

2. 防火墙规则

在企业防火墙上,可以只允许 Claude Code 访问必要的域名:

# 必须允许的域名
api.anthropic.com         # Anthropic API
*.claude.ai               # Claude 服务

# 可选允许(根据使用的功能)
registry.npmjs.org         # npm 包安装
pypi.org                   # Python 包安装
github.com                 # Git 操作

3. 在 settings.json 中禁止网络命令

作为额外的安全层,在 Deny 规则中禁止常见的网络工具:

{
  "permissions": {
    "deny": [
      "Bash(curl:*)",
      "Bash(wget:*)",
      "Bash(nc:*)",
      "Bash(ssh:*)",
      "Bash(scp:*)",
      "Bash(rsync:*)",
      "Bash(ftp:*)",
      "Bash(telnet:*)"
    ]
  }
}

日志审计

对于合规性要求较高的企业,建议建立完整的审计日志体系:

1. 操作日志

通过 Hooks 记录所有工具调用:

{
  "hooks": {
    "PreToolUse": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "python3 -c \"\nimport json, os, datetime\nlog_entry = {\n    'timestamp': datetime.datetime.now().isoformat(),\n    'user': os.environ.get('USER', 'unknown'),\n    'tool': os.environ.get('TOOL_NAME', 'unknown'),\n    'input': os.environ.get('TOOL_INPUT', '')[:500]\n}\nwith open(os.path.expanduser('~/.claude/audit.jsonl'), 'a') as f:\n    f.write(json.dumps(log_entry, ensure_ascii=False) + '\\n')\n\""
          }
        ]
      }
    ]
  }
}

2. 会话日志

Claude Code 自身会保留会话历史,存储在 ~/.claude/ 目录下。企业可以定期备份这些日志。

3. 变更追踪

结合 Git,所有文件变更都有完整的追踪记录。建议 Claude Code 的每次修改都在独立分支上进行,通过 PR 流程合并。

合规性考虑

使用 AI 编程工具可能涉及以下合规问题:

数据安全

风险 应对措施
代码上传到云端 Claude Code 不会上传你的代码到 Anthropic 服务器(除了 API 请求中的上下文)
敏感数据泄露 使用 .claudeignore 排除敏感文件;在 Deny 规则中阻止读取 .env 和密钥文件
API 请求中的敏感信息 避免在对话中粘贴密码、Token 等敏感信息

知识产权

  • Claude Code 的输出(生成的代码)归使用者所有
  • 注意检查 Claude 生成的代码是否包含受版权保护的内容
  • 对于关键业务代码,建议人工审查后再使用

行业合规

  • 金融、医疗等受监管行业可能有额外的 AI 使用限制
  • 确认你的组织是否有关于 AI 工具的使用政策
  • 保持审计日志以满足合规审查需求

安全配置速查表

最后,这里是一份快速参考的安全配置清单:

个人开发者最低安全配置

{
  "permissions": {
    "deny": [
      "Read(.env)",
      "Read(.env.*)",
      "Bash(rm -rf:*)",
      "Bash(git push --force:*)"
    ]
  }
}

团队项目推荐配置

{
  "permissions": {
    "defaultMode": "default",
    "allow": [
      "Bash(npm run:*)",
      "Bash(git status)",
      "Bash(git diff:*)",
      "Bash(git log:*)"
    ],
    "deny": [
      "Read(.env)",
      "Read(.env.*)",
      "Read(secrets/**)",
      "Read(**/*.pem)",
      "Write(.git/**)",
      "Bash(rm -rf:*)",
      "Bash(git push --force:*)",
      "Bash(git reset --hard:*)",
      "Bash(curl:*)",
      "Bash(wget:*)"
    ]
  }
}

高安全企业配置

{
  "permissions": {
    "defaultMode": "default",
    "allow": [
      "Bash(npm run lint)",
      "Bash(npm run test)",
      "Bash(git status)",
      "Bash(git diff)"
    ],
    "deny": [
      "Read(.env)",
      "Read(.env.*)",
      "Read(secrets/**)",
      "Read(**/*.pem)",
      "Read(**/*.key)",
      "Read(**/*credential*)",
      "Read(**/*password*)",
      "Write(.git/**)",
      "Write(.github/**)",
      "Bash(rm:*)",
      "Bash(git push:*)",
      "Bash(git reset:*)",
      "Bash(git checkout -- :*)",
      "Bash(curl:*)",
      "Bash(wget:*)",
      "Bash(ssh:*)",
      "Bash(scp:*)",
      "Bash(nc:*)",
      "Bash(python -c:*)",
      "Bash(node -e:*)",
      "Bash(eval:*)",
      "Bash(exec:*)",
      "Bash(sudo:*)",
      "Bash(chmod:*)",
      "Bash(chown:*)"
    ]
  },
  "hooks": {
    "PreToolUse": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "python3 -c \"import json,os,datetime; f=open(os.path.expanduser('~/.claude/audit.jsonl'),'a'); f.write(json.dumps({'ts':datetime.datetime.now().isoformat(),'user':os.environ.get('USER','?'),'tool':os.environ.get('TOOL_NAME','?'),'input':os.environ.get('TOOL_INPUT','')[:500]},ensure_ascii=False)+'\\n'); f.close()\""
          }
        ]
      }
    ]
  }
}

常见问题

Q:Claude Code 会把我的代码发送到 Anthropic 的服务器吗?

A:Claude Code 通过 API 与 Anthropic 通信,对话上下文(包括你引用的代码片段)会作为 API 请求的一部分发送。但 Anthropic 不会使用通过 API 提交的数据来训练模型(根据 Anthropic 的使用条款)。如果你通过 QCode 等中转服务使用,请参考该服务的隐私政策。

Q:settings.json 中的 Deny 规则能被 Claude 绕过吗?

A:在正常使用下不能。Deny 规则在系统层面强制执行,Claude 无法通过提示词工程或其他方式绕过。但如果你手动选择 bypassPermissions 模式或使用 --dangerously-skip-permissions 参数,这些规则就不再生效。

Q:.claudeignore 和 Deny 规则有什么区别?

A:.claudeignore 让 Claude 完全看不到文件的存在(类似 .gitignore 之于 Git),而 Deny 规则是在 Claude 试图访问时才拒绝。如果你不希望 Claude 知道某些文件的存在,用 .claudeignore;如果只是不想让它修改,用 Deny 规则。

Q:多人协作时,每个人的 settings.json 不同怎么办?

A:项目级的 .claude/settings.json 提交到 Git,确保团队共享统一的安全基线。个人的 ~/.claude/settings.json 中可以添加额外配置,但不能覆盖项目级的 Deny 规则。

Q:在 Docker 容器中使用 Claude Code 是否更安全?

A:是的。Docker 提供了额外的隔离层,即使 Claude Code 执行了意外的操作,影响也被限制在容器内。建议在容器中:使用只读挂载源代码目录、限制网络访问、使用非 root 用户运行。

🚀
开始使用 QCode — AI 编程助手
Claude Code 官方中继,稳定快速,开箱即用
查看套餐定价 → 注册账号