
做代码审计的人最近大概都在讨论同一个组合Claude Skills自动漏洞挖掘。我第一次在终端里把Claude Code的Skills打开、让它顺着数据流自己找SQL注入时说实话有点恍惚——这不就是我以前加班做的事吗过去那种“人工读代码→画数据流→查危险函数→写报告”的流程现在有一部分能被一个会读代码的AI Agent接住了。这篇文章不是理论分析是我实际跑过的项目总结。我会从Claude Code和Skills的基本概念讲起带着你一步步搭好环境然后手写一个可用于漏洞挖掘的Skill最后在本地靶场上完整跑一遍流程。适合正在做代码审计、想用AI提效的安全测试工程师也适合写业务代码时想顺手自查漏洞的开发者。我会尽量讲清楚每一步为什么这么做以及我踩过的坑。1. 为什么Claude Skills能做自动漏洞挖掘1.1 先把概念对齐Claude Code到底是什么Claude Code是Anthropic推出的终端AI编程Agent和网页版对话不一样的是它能直接工作在项目目录里。它拥有读文件、改文件、执行命令、搜索代码、查看git历史的能力。你可以把它理解成一个长在你终端里的“结对程序员”而且这个程序员有完整的仓库访问权限。自动漏洞挖掘这件事天然依赖上下文。一个SQL注入漏洞可能入口在index.php里通过$_GET接收参数中间经过三层业务封装最后落到某个model里的SQL拼接。如果只把那一行可疑代码贴给AI它根本看不出问题但如果允许它在整个仓库里自由走动、追踪数据流它就能还原完整链路。Claude Code的“项目内Agent”形态刚好补上了传统对话式AI最缺的一环。我第一次用的时候让它“看一下这个项目的登录逻辑”它会自己搜索路由、打开控制器文件、翻到SQL语句、回来看请求参数怎么进来的。这种能力不是花架子它就是漏洞挖掘最需要的“跨文件追踪能力”。1.2 Skills机制等于给AI装“专用工具箱”Claude Code虽然能读代码但是“能读”和“知道怎么挖洞”是两码事。普通的对话模式下你每次都要花很长篇幅去告诉它先看哪里、用什么思路判断、输出格式是什么、不要碰哪些文件。只要对话一多AI就会飘判断标准前后不一致。Skills机制解决的就是这个问题。它允许你把一套完整的工作方法、判断标准、脚本工具打包成固定技能模型在合适的场景下自动加载。一个Skill就是一组文件核心是目录下的SKILL.md里面用自然语言写清楚这个技能什么时候用、怎么执行、遵守什么规则旁边还可以放辅助脚本。我刚接触时用的是社区很火的superpower skills那是一套通用型技能包里面覆盖了浏览器操作、图片生成、文件整理之类的偏通用能力。但它毕竟是通用技能漏洞挖掘这种高度领域化的场景现成技能帮不了太多。于是我开始自己写Skill把以前做审计的流程固化下来。第一次跑通的时候我意识到一件事Skill不是“插件市场里下载的成品”而是一个把个人经验变成可复用方法论的好载体。1.3 与传统扫描器的本质区别和它带来的改变传统的代码安全扫描器不管是SAST还是DAST核心逻辑都是“规则匹配”。扫描器看到mysql_query($sql)且$sql里有变量就会报一个SQL注入。问题在于规则不理解业务逻辑于是要么漏报比如危险函数被封装了一层规则看不穿要么误报一堆实际上根本没有用户可控路径的“假漏洞”。Claude Skills这套组合提供了一条不一样的路规则扫描产生候选模型做语义判断。Agent能跨文件追踪数据流能理解某个参数到底是不是用户可控能判断危险函数前面有没有充分过滤。说白了它不只是报“这里有危险函数”而是会告诉你“这个变量从HTTP请求进来一路没过滤最终拼进了SQL所以这是真实的漏洞”还会顺手把修复代码写出来。影响范围确实不小。对于安全团队基础审计和报告撰写能省下大量时间对于业务开发团队等于每个人都有了一个随叫随到的代码安全顾问对于小团队和甲方内部项目以前可能雇不起专门的审计现在用AI做一轮初步筛查完全可行。当然它也替代不了人AI的幻觉问题、误判问题、上下文窗口限制都是绕不过去的坎。这套方案的定位更准确的说法是“一个能干的实习审计员但需要你当评审”。2. 环境准备先把Claude Code和Skills跑起来2.1 安装Claude Code的两种方式与初始化登录Claude Code的安装在我看来已经算很亲民了。它依赖Node.js环境只要你的机器上已经有Node.js 18以上的版本一条命令就能装完npm install -g anthropic-ai/claude-code装完之后在任意项目目录里输入claude就能启动。首次启动会让你登录账号授权按照终端里给的链接操作就行。我在Windows上遇到过不少问题这里重点说一个。有些机器启动时直接报错大意是“Claude’s workspace requires the virtual machine platform on Windows”。这个不是Claude Code本身的问题是Windows的虚拟机监控程序平台没打开。解决方法是控制面板→启用或关闭Windows功能→勾选“虚拟机监控程序平台”和“Windows虚拟机监控程序平台”重启后通常就好了。如果你平时在用WSL也可以直接在WSL的Linux环境里跑Claude Code体验会更顺畅文件IO和权限模型的坑会少很多。还有个小建议不要从网上随意下载来路不明的“汉化版”“绿色版”安装包就老老实实用官方npm包。安全工具领域供应链污染是个大威胁别为了省几秒钟担这种风险。2.2 理解Skills的目录结构与SKILL.md规范Skills的存放位置最常用的是两个全局目录~/.claude/skills/和项目目录.claude/skills/。放全局目录意味着所有项目都能用放项目目录则只对该项目生效适合团队里统一分发。一个Skill的基本结构长这样~/.claude/skills/ vuln-hunter/ SKILL.md scripts/ scan.pySKILL.md是这个技能的灵魂。它有固定的格式要求文件最开头用YAML frontmatter写元信息其中name和description是核心字段。之后正文部分用普通Markdown写执行步骤和规则。我最初以为description只是给人类看的说明后来才发现它直接决定了Claude Code什么时候加载这个技能。当你在对话中表达“扫描一下这个项目的安全问题”时Claude Code会扫描所有可用的Skill读它们的description判断哪个匹配当前任务。所以description里一定要写清楚这技能干什么、在什么场景下触发最好把常见的意图词都覆盖到比如“SQL注入”“XSS”“代码审计”“漏洞”都要写进去。很多Skill不生效根源就出在description写得太含糊。2.3 安装现成Skills以superpower skills为例如果你只是想先体验一下Skills的工作方式装一套社区成熟的技能包是最快的。比如superpower skills它的安装方式本质上就是“把仓库clone到Skills目录里”。我当时的做法是git clone https://github.com/obra/superpowers.git ~/.claude/skills/superpowers装完后重启Claude Code再提问时它就能识别到这些技能。实际用下来这套技能包里的方向偏“提升Agent工程效率”比如让Claude更好地分析任务、生成结构化文档、做子代理规划这些能力对写代码是很有用的。但这里也要泼一盆冷水现成技能包通常覆盖的是通用能力不是安全审计专用。如果你真想体验自动漏洞挖掘最靠谱的还是自己写一个专属Skill把扫描脚本、判断规则、输出格式都控制在自己手里。别指望下载一个大而全的“超级技能包”就能一劳永逸任何跟特定业务逻辑强相关的能力最终都得自己做定制。3. 设计一个漏洞挖掘Skill把审计经验固化成代码3.1 先拆解人工审计流程再翻译成Skill工作流我写Skill之前没有直接动手敲代码而是先把自己以前做人工审计的流程完整走了一遍。把一个典型的代码审计任务拆开差不多是这几步首先是理解项目结构搞清楚路由入口、中间件、数据库层在哪里然后是找输入点也就是HTTP参数、用户上传文件、反序列化入口这些地方接着追踪数据流看输入经过了哪些函数、做了哪些过滤有没有走到危险函数最后是验证和写报告。这个流程天然适合让Agent来做因为它有那么大的上下文窗口和代码浏览能力。但问题在于如果每一步都靠“现场发挥”AI很容易在某个环节跑偏。所以我要把所有这些步骤写进SKILL.md里并且明确给模型划定边界。Skill工作流我最终设计成了四个阶段信息收集让模型先浏览目录结构找出路由和入口点。静态扫描调用辅助脚本快速定位危险函数的候选位置。威胁研判对每个候选点模型要给出完整的数据流和影响范围。报告输出按统一格式输出漏洞清单、置信度、修复建议。把工作流固定下来有个好处不管项目是谁写的、代码多乱AI至少会按一个标准套路走输出质量更加可控。3.2 一个最小可用的vuln-hunter Skill实例下面是我实际在用的简化版Skill。目录结构就是标准的SKILL.md加scripts/scan.py。先看SKILL.md的内容--- name: vuln-hunter description: Source code security audit. Use when user asks to scan code, find vulnerabilities, hunt bugs, check SQL injection, XSS, SSRF, command injection, insecure deserialization, or any security review task. --- # Vulnerability Hunter You are a careful and cautious source code auditor. Your job is to find security issues and present evidence-backed findings. ## Workflow 1. First, list the top-level directory structure to understand the project layout. 2. Identify input entry points: HTTP request parameters, environment variables, file uploads, deserialization call sites. 3. Run the helper scanner to find candidate suspicious lines: python3 scripts/scan.py target-dir 4. For each candidate, verify whether untrusted input can actually reach the dangerous function. If the chain is incomplete, mark the finding as low confidence. 5. Never modify source files. Never download or execute tools without explicit permission. 6. Output a structured report: - Vulnerability type - File and line number - Evidence snippet - Data flow / attack path - Confidence level (high / medium / low) - Remediation suggestion ## Rules - Only analyze code inside the workspace. - Do not exaggerate uncertain findings. - If you find nothing, explicitly say so instead of making something up.配套的scripts/scan.py我这个版本为了演示写得很轻量核心是扫描一批常见危险函数的关键词输出候选点。实际工程环境里我会建议把它的定位放大为“找可疑点的线索引擎”而不是“结论引擎”。#!/usr/bin/env python3 import os import sys import json DANGEROUS { eval: code execution, exec: code execution, os.system: command injection, subprocess.Popen: command injection, subprocess.run: command injection, pickle.loads: insecure deserialization, yaml.load: insecure deserialization, mysql_query: sql injection, cursor.execute: sql injection, db.execute: sql injection, innerHTML: dom xss, dangerouslySetInnerHTML: react xss, } def scan_file(path): findings [] try: with open(path, r, encodingutf-8, errorsignore) as f: lines f.readlines() except Exception: return findings for idx, line in enumerate(lines, 1): for pattern, vuln_type in DANGEROUS.items(): if pattern in line: findings.append({ file: path, line: idx, pattern: pattern, type: vuln_type, snippet: line.strip()[:200], }) break return findings def main(target): all_findings [] for root, _, files in os.walk(target): if any(part in root for part in (node_modules, .git, vendor, dist, build)): continue for filename in files: if filename.endswith((.php, .py, .js, .ts, .jsx, .tsx, .java, .go)): path os.path.join(root, filename) all_findings.extend(scan_file(path)) print(json.dumps(all_findings, indent2)) if __name__ __main__: if len(sys.argv) 2: print(Usage: python3 scan.py target-dir) sys.exit(1) main(sys.argv[1])你可能觉得这个脚本太简单但这是刻意为之。漏洞挖掘里最怕的就是“脚本一步到位”的错觉——代码分析的复杂度远超任何规则集。脚本的价值是缩小范围把一个几十万行的项目缩减成几百个候选点真正判断这些候选中哪些是漏洞、哪些是误报依赖的是Claude的跨文件推理能力。两边分工才最高效。写完后把vuln-hunter目录放到~/.claude/skills/下重启Claude Code这个技能就算安装上了。3.3 关键设计让AI不越权、不误改、不跑偏我一开始写的Skill没有加“只读”约束结果Claude跑着跑着居然“好心”地帮我把一个可疑的SQL拼接改成参数化查询了。听着像是好事但审计过程中无授权修改代码是大忌一旦改出事你根本没法交代。所以在Skill里必须明确宣告只分析不修改。这个约束既要写在SKILL.md里也要在运行时配合Claude Code的权限模式做双重保险。Claude Code支持通过--permission-mode或者交互式授权来限制它能做什么把文件写入权限关掉让Agent只能读和跑扫描命令。还有一点容易被忽略AI有讨好倾向。你不限定它就倾向于多报一些问题来显得自己“有干活”结果就是误报率飙升。我在设计Skill时要求所有结论必须带证据——至少给出“输入入口→经过函数→到达危险函数”的完整链路拿不出链路就标低置信度。这个小改动直接把报告质量拉高了一个档次。4. 实操实录在本地靶场上跑通自动挖掘4.1 准备实验目标DVWA本地靶场不能拿生产环境测试AI挖洞这是铁律。本地搭靶场最方便的选择是DVWADamn Vulnerable Web Application它就是故意设计了各种漏洞的教学项目用来验证AI挖掘能力再合适不过。我用Docker起DVWA的方式很简单git clone https://github.com/digininja/DVWA cd DVWA docker compose up -d服务起来之后浏览器访问本机端口就能看到登录页默认账号密码是admin/password。这里有个细节DVWA的源码会映射到本地的src目录Claude Code要分析的是源码而不是运行容器。我会把终端切到src目录再启动Claude Code这样Agent只在这个代码范围内操作不会跑偏去看Docker相关文件。靶场的意义在于你可以放心让它随便造造出问题也不会有实际损失。我强烈建议所有想做AI自动漏洞挖掘的人都先拿DVWA这类靶场练手摸清楚模型的行为模式再考虑真实代码。4.2 让Claude Code自动定位SQL注入与XSS在src目录下启动Claude Code后我输入的关键讲义是这样的用 vuln-hunter 扫描当前项目重点关注 SQL Injection 和 Stored XSS。 对每个可疑点输出漏洞类型、文件与行号、触发参数、完整数据流、置信度、修复建议。 整个过程只做分析不要修改任何源码。这个prompt有几个刻意的设计指定了漏洞类型避免AI“全都要查”导致精力分散要求输出数据流等于强制它做跨文件追踪最后一句“不要修改源码”是双保险防止它手痒。实际运行效果比我预期的好。Claude Code会先列目录找到vulnerabilities/sqli/这个目录然后打开source/low.php顺着$_GET[id]参数一路追踪到mysql_query并给出了类似这样的判断第 28 行的$id直接来自$_GET[id]没有经过任何过滤或类型转换随后被拼接到 SQL 查询中。这构成完整的用户输入到危险函数的数据流初步判定为高危 SQL 注入。它甚至能指出这是low级别的代码而不是medium或high。这说明模型在比对同目录下不同版本的文件这已经是“理解代码语义”而不是“匹配规则”了。整个过程里我要做的就是在关键节点上追问一句“你确定吗”“证据链完整吗”。大多数情况下它都能给出合理的解释。4.3 人工验证环节与报告整理AI给的结果再漂亮也不能直接写进交付报告必须人工验证。我验证SQL注入的习惯是登录DVWA给请求参数加一个单引号或者一个恒真条件看数据库是否报错、页面是否异常。比如访问http://localhost:8080/vulnerabilities/sqli/?id1%27SubmitSubmit如果页面出现SQL语法错误就说明拼接点确认存在。这一步没法省AI的幻觉能力比你想的强它经常能把一个“看起来像漏洞”的地方说得头头是道实际上那条代码路径根本走不通。为了方便跟踪我用一个表格管理AI产出的线索和验证状态漏洞类型位置数据流摘要AI置信度人工验证结果SQL注入src/vulnerabilities/sqli/source/low.php:28$_GET[id]-$id-mysql_query高已复现确认存在存储型XSSsrc/vulnerabilities/xss_s/source/low.php$_POST[txtName]-INSERT- 页面输出中已复现确认存在反射型XSSsrc/vulnerabilities/xss_r/source/low.php$_GET[name]- 直接echo高已复现确认存在整理完之后再让它根据验证结果生成最终报告。Claude Code生成报告的速度比人工整理快太多了而且格式统一。不过报告末尾我会补一段“人工复核说明”明确哪些点经过了真实验证哪些还需要深入测试。5. 常见问题与排坑手册5.1 Skill不生效先从这三个地方查我折腾Skills的前两天遇到最多的就是“我明明把Skill放进目录了但Claude Code理都不理”。第一个检查点是目录结构。SKILL.md必须直接放在技能目录的根下面比如~/.claude/skills/vuln-hunter/SKILL.md。如果多套了一层文件夹或者文件名大小写写成了skill.md模型就识别不到。第二个检查点是description。前面提过Claude Code靠description匹配意图。如果description里只写了“A security tool”模型在遇到“帮我审计一下代码”时根本不会联想到它。把触发词写全是一门容易被忽略的手艺。第三个检查点是路径。如果Skill放在项目目录.claude/skills/下一定要确认Claude Code是在项目根目录启动的。有些时候我直接在子目录里启动模型就看不到项目的skills了。还有一个傻乎乎的坑是改了Skill后没重启进程Claude Code在对话期间不会保持实时热更新重启一下大多数问题就解决了。5.2 误报太多、AI像在编答案给它加“验证约束”用AI做漏洞挖掘最大的痛点是幻觉。模型为了给出有意义的回答会在证据不足的情况下强行补充细节把不存在的问题说得像真事。我这里有个实测有效的方法在Skill里强制要求“输出置信度”和“完整数据流”。置信度不高的一律默认不写进最终报告数据流不完整的不允许判定为漏洞。这等于逼它在下结论前把推理路径摆出来而摆不出来的就自动降级。跑上一两轮报告质量会明显提升。还有一个经验是缩小扫描范围。让AI一次扫描整个项目它的上下文窗口会被冲散注意力分摊到几十个文件上误报率自然高。我实践下来的最佳方式是分类型、分模块扫描先专查SQL注入再专查XSS先看核心业务模块再看边缘工具脚本。整体耗时可能差不多但准确率差别很大。5.3 安全边界哪些活不能交给自动挖掘用AI挖漏洞这件事有些边界是绝对不能碰的。首先未经授权的目标一概不测。自动漏洞挖掘的本质是代码审计但它跑出来的结果很可能直接指向可利用的漏洞。你拿它扫自己的项目、扫公司授权的系统、扫本地靶场都没有问题但拿它去扫一个你不拥有、也没有书面授权的外部系统这就是越界行为。哪怕AI只是“看看”也不行。其次不要让AI生成可用的攻击武器。它可能会顺带给出一个绕过验证码的完整脚本或者把漏洞利用过程自动化。我在实际使用中会刻意在提示词里加上“只描述问题与修复方法不生成完整利用代码”。这既是保护自己也是对漏洞负责任。最后要记住AI自动挖掘是提高效率的工具不是替代安全决策的“法官”。最终哪些风险可接受、哪些必须修复、怎么排优先级还是要靠人。工具越强越需要清醒的头脑去把握它的使用边界。我自己跑完这一套流程之后最大的体感是Claude Skills自动漏洞挖掘不是一个“输入命令就出报告”的黑盒它更像一个能力很强的实习生——你得给它划定范围、定好规则、把方法论讲清楚它才能真正帮上忙。如果你也想试建议从今天说的本地靶场开始写一个几十行的SKILL.md跑通一次完整的“扫描→分析→验证→报告”流程。只要第一次跑通了后面你就会发现这个组合比想象中好用得多。