AI 安全漏洞分析自动化:用 Claude 写一个能读懂你整个代码库的安全审计工具
AI 安全漏洞分析自动化:用 Claude 写一个能读懂你整个代码库的安全审计工具
很多人用 AI 审代码,都是把文件一段段粘贴进去,然后问"这里有没有安全问题"。
这种方式有个根本缺陷:AI 看不到上下文。一个函数里的 SQL 拼接是不是漏洞,取决于调用方有没有做输入校验。割裂地看,误报率极高,真正的问题反而容易漏掉。
HN 今天有篇讨论:"AI is breaking two vulnerability cultures",核心观点是 AI 正在同时冲击两种安全文化——一种是"靠人工慢慢审",另一种是"靠规则引擎扫描"。AI 的优势在于能理解语义,但前提是你得把足够的上下文喂给它。
下面这个工具就是解决这个问题的:把整个 repo 的结构和关键文件一次性组织好,交给 Claude 做系统性安全审计。
思路
1. 递归遍历项目,过滤掉无关文件(node_modules、.git 等)
2. 优先读取高风险文件:路由定义、数据库操作、认证逻辑、配置文件
3. 构建一个结构化的 prompt,包含文件树 + 关键文件内容
4. 调用 Claude API,要求输出结构化的漏洞报告
整个流程大概 50 行 Python,跑一次能覆盖中小型项目的主要风险面。
完整代码
import os
import json
from pathlib import Path
from openai import OpenAI
# 无量Api 兼容 OpenAI 格式,改一行 base_url 即可
client = OpenAI(
api_key="your-api-key", # 在 api2everything.xyz 注册获取
base_url="https://api2everything.xyz/v1"
)
# 高风险文件关键词,优先读取
HIGH_RISK_PATTERNS = [
"route", "router", "controller",
"auth", "login", "token", "jwt",
"db", "database", "query", "model",
"config", "env", "setting",
"upload", "file", "exec", "shell"
]
SKIP_DIRS = {
"node_modules", ".git", "__pycache__", ".venv",
"venv", "dist", "build", ".next", "coverage"
}
SKIP_EXTS = {
".png", ".jpg", ".jpeg", ".gif", ".svg", ".ico",
".lock", ".sum", ".min.js", ".map"
}
def should_skip(path: Path) -> bool:
for part in path.parts:
if part in SKIP_DIRS:
return True
if path.suffix in SKIP_EXTS:
return True
return False
def is_high_risk(path: Path) -> bool:
name = path.stem.lower()
return any(pattern in name for pattern in HIGH_RISK_PATTERNS)
def collect_files(root: str, max_files: int = 60):
root_path = Path(root)
all_files = []
high_risk_files = []
for p in root_path.rglob("*"):
if p.is_file() and not should_skip(p):
rel = p.relative_to(root_path)
if is_high_risk(p):
high_risk_files.append(rel)
else:
all_files.append(rel)
# 高风险文件优先,总数控制在 max_files 以内
selected = high_risk_files[:max_files // 2]
remaining = max_files - len(selected)
selected += all_files[:remaining]
return sorted(selected), high_risk_files
def build_file_tree(root: str, files: list) -> str:
lines = [f"项目根目录: {Path(root).name}/"]
for f in files:
lines.append(f" {f}")
return "\n".join(lines)
def read_file_safe(path: Path, max_chars: int = 3000) -> str:
try:
content = path.read_text(encoding="utf-8", errors="ignore")
if len(content) > max_chars:
content = content[:max_chars] + "\n... [文件过长,已截断]"
return content
except Exception as e:
return f"[读取失败: {e}]"
def build_prompt(root: str, files: list, high_risk: list) -> str:
root_path = Path(root)
tree = build_file_tree(root, files)
sections = [
"你是一名资深安全工程师,请对以下代码库进行安全审计。",
"",
"## 项目文件结构",
"```",
tree,
"```",
"",
"## 高风险文件内容(重点审查)",
]
for rel in high_risk[:20]: # 最多读 20 个高风险文件
full_path = root_path / rel
content = read_file_safe(full_path)
sections += [
f"\n### {rel}",
"```",
content,
"```"
]
sections += [
"",
"## 审计要求",
"请按以下格式输出报告,每个问题单独列出:",
"",
"**[严重程度: 高/中/低]** 漏洞类型",
"- 位置: 文件名:行号(如能判断)",
"- 描述: 具体问题",
"- 利用方式: 攻击者如何利用",
"- 修复建议: 具体代码级别的修复方案",
"",
"重点关注:SQL注入、XSS、CSRF、不安全的反序列化、",
"硬编码密钥、路径遍历、命令注入、不当的权限校验、",
"敏感信息泄露、不安全的依赖。",
"",
"最后给出一个总体安全评分(0-100)和优先修复建议。"
]
return "\n".join(sections)
def audit_repo(repo_path: str, model: str = "claude-sonnet-4-5"):
print(f"正在扫描项目: {repo_path}")
files, high_risk = collect_files(repo_path)
print(f"共发现 {len(files)} 个文件,其中高风险文件 {len(high_risk)} 个")
prompt = build_prompt(repo_path, files, high_risk)
print(f"Prompt 长度: {len(prompt)} 字符,正在调用 Claude...")
response = client.chat.completions.create(
model=model,
messages=[
{"role": "user", "content": prompt}
],
max_tokens=4096,
temperature=0.2 # 安全审计需要确定性输出
)
report = response.choices[0].message.content
# 保存报告
output_file = Path(repo_path) / "security_audit_report.md"
output_file.write_text(f"# 安全审计报告\n\n{report}", encoding="utf-8")
print(f"\n报告已保存至: {output_file}")
print("\n" + "="*60)
print(report)
if __name__ == "__main__":
import sys
path = sys.argv[1] if len(sys.argv) > 1 else "."
audit_repo(path)
使用方式
pip install openai
python audit.py /path/to/your/project
报告会直接生成在项目根目录下的 security_audit_report.md。
几个实际跑出来的发现
在一个 Express + MongoDB 的项目上跑了一次,Claude 找到了:
- 一个
find()查询直接把req.query传进去,NoSQL 注入风险 - JWT secret 写在代码里而不是环境变量
- 文件上传接口没有校验 MIME 类型,只校验了扩展名
这三个问题,传统的静态扫描工具(ESLint security 插件)只发现了第三个。
关于模型选择和成本
这类任务 prompt 比较长(通常 8k-20k token),用官方 Claude API 跑一次大概要 $0.5-1。
我现在用的是 无量Api,同样的 claude-sonnet-4-5,价格是官方的 35% 左右,注册还送 ¥1 余额可以直接试。接入方式就是改一行 base_url,代码里已经写好了,直接用就行。
对于这种批量跑、频繁迭代的工具脚本,省下来的成本还是很可观的。
扩展方向
- 接入 GitHub Actions,每次 PR 自动触发审计
- 对比两次审计结果,只报告新增漏洞
- 针对特定框架(Django、Spring)定制高风险文件识别规则
代码逻辑不复杂,核心是上下文组织的方式。AI 能不能给出有价值的结论,80% 取决于你怎么喂数据。
有问题或者跑出来有意思的发现,评论区聊聊。觉得有用的话点个赞,后续还会写更多这类可以直接跑的工具。