
1. 为什么安全团队开始用 Claude Code CLI 做代码审计代码审计这件事过去基本靠人肉翻源码加规则引擎扫。规则引擎能覆盖已知模式但遇到业务逻辑漏洞、权限绕过、越权访问这类需要读懂上下文的问题规则库就力不从心了。我试过把一段存在越权风险的接口代码丢给传统 SAST 工具它只报了个未校验参数而实际上问题出在鉴权中间件的执行顺序上——这种跨文件的语义问题规则引擎很难串起来。Claude Code 是 Anthropic 推出的终端 AI 编程 Agent运行在 CLI 里能读取整个代码库、执行命令、处理 git 工作流。它和网页聊天式 AI 最大的区别是它真的能进到你的项目里按目录结构理解调用链而不是你手动粘贴几段代码。对于安全场景自动化来说这意味着你可以把审计做成一条流水线——触发、扫描、分析、出报告中间不需要人反复搬运上下文。这篇面向三类人一是想把代码审计半自动化的安全工程师二是需要给 CI 加一道 AI 审计关卡的后端团队三是刚接触 Claude Code、想搞清楚 CLI 和 MCP 怎么串起来的新手。我会从环境配置讲到 settings.json 骨架再给一条从触发到出报告的完整验证动作。全程用 TaoToken 作为统一 API 通道省去多厂商 Key 管理的麻烦。2. TaoToken 前置统一 Key 与 API 通道配置Claude Code 默认走 Anthropic 官方接口但实际做安全审计时你可能想在不同模型间切换——比如用 Claude 做深度语义分析用国产模型做批量日志初筛。如果每个厂商都单独配 Key、单独改 base_url配置会散得到处都是。TaoToken 的思路是提供一个统一入口你只维护一个 Key模型切换通过参数控制。先拿到 Key。访问 https://taotoken.net/api-keys 创建格式类似sk-开头的一串字符。这个 Key 同时能调 Claude、GPT、Gemini 以及豆包、千问、DeepSeek 等国内模型计费按量走。拿到 Key 后Claude Code 需要三个环境变量才能把请求指向 TaoTokenexport ANTHROPIC_AUTH_TOKENsk-你的TaoToken密钥 export ANTHROPIC_BASE_URLhttps://taotoken.net/api export ANTHROPIC_MODELclaude-sonnet-4-20250514这里有个坑要注意ANTHROPIC_BASE_URL填的是https://taotoken.net/api不要带末尾斜杠也不要自己拼/v1。Claude Code 内部会按 Anthropic 的路径规范去拼/v1/messages你多写一层反而 404。我第一次配的时候手贱加了/v1结果一直报404 not found排查了半小时才发现是路径重复。如果你想让配置持久化别每次开终端都 export写进~/.zshrc或~/.bashrcecho export ANTHROPIC_AUTH_TOKENsk-你的密钥 ~/.zshrc echo export ANTHROPIC_BASE_URLhttps://taotoken.net/api ~/.zshrc echo export ANTHROPIC_MODELclaude-sonnet-4-20250514 ~/.zshrc source ~/.zshrc模型名这块TaoToken 支持用别名。比如你想临时切到更便宜的模型做批量扫描可以在启动时用--model覆盖claude --model claude-haiku-4-20250514 -p 扫描 src/ 下的 SQL 注入风险这样环境变量里的默认模型不变单次会话用指定模型适合深度分析用 Sonnet、批量初筛用 Haiku的分层策略。3. 可复制配置settings.json 与 config.toml 骨架Claude Code 的配置分两层一层是项目级的.claude/settings.json控制权限、工具白名单、MCP 服务器另一层是用户级的~/.claude/config.toml部分版本用~/.claude.json控制全局偏好。安全审计场景下这两层都要收紧避免 Agent 在扫描时误改代码或执行危险命令。先看项目级settings.json。放在项目根目录的.claude/下{ permissions: { allow: [ Read, Glob, Grep, Bash(git log:*), Bash(git diff:*), Bash(semgrep:*), Bash(npm audit:*) ], deny: [ Write, Edit, Bash(rm:*), Bash(curl:*), Bash(wget:*) ] }, mcpServers: { filesystem: { command: npx, args: [-y, modelcontextprotocol/server-filesystem, ./src] }, git: { command: npx, args: [-y, modelcontextprotocol/server-git, --repository, .] } } }这份配置的核心逻辑是只读不写。审计场景下Agent 不应该有修改代码的权限否则它可能顺手帮你修 bug反而引入新问题。deny里禁掉Write、Edit和rmallow里只放读取和只读命令。Bash(curl:*)也禁掉防止 Agent 把代码片段外发。MCP 部分挂了两个服务器filesystem 限定在./src目录git 用于读取提交历史。MCP 是 Model Context Protocol 的缩写你可以理解成给 Agent 插的外设——它让 Agent 能通过标准协议调用外部工具而不是靠拼 shell 命令。filesystem 服务器让 Agent 能列目录、读文件git 服务器让它能查 diff、看 blame这些在审计里都是关键上下文。再看用户级~/.claude/config.toml[model] default claude-sonnet-4-20250514 fallback claude-haiku-4-20250514 [api] base_url https://taotoken.net/api timeout 120 [security] strict_mcp_config true dangerously_skip_permissions false [output] format stream-json verbose falsestrict_mcp_config true这个开关很重要。它让 Claude Code 只加载--mcp-config或 settings.json 里显式声明的 MCP 服务器忽略其他来源的配置。安全场景下你不希望某个全局配置里偷偷挂了个能访问生产库的 MCP 服务器。dangerously_skip_permissions必须保持 false那个--dangerously-skip-permissions参数只建议在无网络的沙盒里用生产审计环境千万别开。output.format stream-json是为了后续接流水线。流式 JSON 输出方便你用脚本解析每一步的工具调用和结果而不是等它全部跑完再拿一大坨文本。4. 验证请求从触发到出报告的完整动作配置写完得验证整条链路能跑通。我设计了一个最小可复现的验证动作对一个存在已知漏洞的示例项目做审计看它能不能定位到问题并输出结构化报告。先准备一个测试项目。建个目录放一个有明显 SQL 注入的 Node.js 文件mkdir -p ~/audit-demo/src cd ~/audit-demo cat src/user.js EOF const express require(express); const mysql require(mysql); const app express(); const db mysql.createConnection({ host: localhost, user: root, password: root, database: test }); app.get(/user, (req, res) { const id req.query.id; const sql SELECT * FROM users WHERE id ${id}; db.query(sql, (err, result) { if (err) throw err; res.json(result); }); }); app.listen(3000); EOF这段代码里id直接拼进 SQL是教科书级的注入漏洞。现在用 Claude Code 做非交互式审计cd ~/audit-demo claude -p 审计 src/ 目录下的代码找出所有安全漏洞按严重程度排序输出 JSON 格式每条包含文件路径、行号、漏洞类型、修复建议 \ --output-format json \ --allowedTools Read,Glob,Grep \ --settings .claude/settings.json注意这里用了-p进入非交互模式--output-format json让结果结构化--allowedTools临时限定工具范围。跑完之后你会拿到类似这样的输出{ result: 发现 1 个高危漏洞, findings: [ { file: src/user.js, line: 8, type: SQL Injection, severity: high, detail: 用户输入 id 未经过滤直接拼接进 SQL 查询语句, fix: 使用参数化查询db.query(SELECT * FROM users WHERE id ?, [id], ...) } ] }如果这一步能出结果说明从环境变量、API 通道到 MCP 工具链整条链路是通的。接下来把它接进流水线用 git hook 触发cat .git/hooks/pre-push EOF #!/bin/bash echo 运行 AI 安全审计... claude -p 审计本次变更涉及的文件只报告新增的安全问题 \ --output-format json \ --allowedTools Read,Glob,Grep,Bash(git diff:*) \ audit-report.json if grep -q severity: high audit-report.json; then echo 发现高危漏洞阻止推送 exit 1 fi EOF chmod x .git/hooks/pre-push这样每次 push 前自动跑一遍审计有高危就拦下来。报告落在audit-report.json后续可以接通知或存档。5. 本篇常见错排查配这套流程时我踩过的坑集中在几个地方列出来帮你省时间。报错401 Unauthorized或invalid api key先检查ANTHROPIC_AUTH_TOKEN有没有多余空格或换行。用echo $ANTHROPIC_AUTH_TOKEN | xxd | head看下首尾字节。另一个常见原因是 Key 复制时漏了字符重新去 https://taotoken.net/api-keys 复制一遍。报错404 not found或model not found八成是ANTHROPIC_BASE_URL写错了。正确值是https://taotoken.net/api不要加/v1不要加末尾斜杠。模型名也要对claude-sonnet-4-20250514这种全名最稳别名有时会因版本差异解析失败。MCP 服务器起不来报command not foundMCP 服务器大多通过npx拉起确保本机 Node.js 版本 ≥ 18。如果 npx 拉包慢可以先手动npm install -g modelcontextprotocol/server-filesystem再在配置里把command改成绝对路径。审计结果为空Agent 说未发现漏洞检查--allowedTools有没有把Read和Grep放进去。如果只给了BashAgent 没法直接读文件内容只能靠 shell 命令猜效果差很多。另外确认settings.json里的deny没有误伤Read。输出不是 JSON混了一堆日志--output-format json只在-p非交互模式下生效。如果你没加-p它进交互模式输出格式参数被忽略。另外--verbose开着也会往 stdout 混调试信息审计流水线里记得关掉。权限被拒Agent 说没有权限执行这是settings.json的permissions.deny在起作用。审计场景下这是预期行为但如果你确实需要某个命令把它加到allow里而不是直接开--dangerously-skip-permissions。6. 把审计流水线接进日常下一步怎么走跑通上面这条链路后你可以按团队情况做扩展。如果只是个人项目pre-push hook 够用了如果是团队 CI把claude -p那步包成脚本在 GitHub Actions 或 GitLab CI 里跑报告作为 artifact 存档。模型选择上我的建议是分层批量初筛用 Haiku 这类快而便宜的模型把明显问题过滤出来对初筛标记的可疑点再用 Sonnet 做深度语义分析。TaoToken 的统一 Key 让这种切换只改一个--model参数不用重新配环境。MCP 这块filesystem 和 git 是基础后续可以按需挂更多。比如接一个依赖扫描的 MCP 服务器让 Agent 在审计代码的同时查 CVE或者接一个内部知识库的 MCP让它对照你们的安全编码规范给修复建议。MCP 的价值在于把审计从单点分析变成有外部上下文支撑的推理。如果你想把 Claude Code 用在长期编码和 Agent 场景可以了解下 Coding Planhttps://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding-planutm_campaignrewrite 。需要调模型做对比测试的话模型对话入口在 https://taotoken.net/chat?utm_sourcetaotoken_aicg_blog_endutm_contentmodel-chatutm_campaignrewrite 。接入文档在 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 控制台在 https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_contentconsoleutm_campaignrewrite 。最后说个实操细节审计报告别只存 JSON让 Agent 同时输出一份 Markdown 摘要方便贴到 PR 评论里。可以在提示词里加一句同时输出人类可读的 Markdown 版本它会一并给你。这样开发同学不用去翻 JSON直接在 PR 里看到问题和修复建议闭环更快。