从0到1构建安全审计Skill:基于AI Agent的自动化审计实践 最近 Skill 这个概念在 AI 圈子里被聊得很多Claude Skill、Codex Skill、OpenCode Skill 层出不穷我在实际试了一圈之后自己动手整理了一个专门做安全审计的 Skill取名security-audit-skill。起因其实很朴素我平时既要写代码又要给团队维护一套内部的安全审计规范。每次做系统上线前的安全检查流程都差不多——通过扫描工具收集资产信息、核对配置基线、翻日志找异常、最后整理报告。这套流程重复性极高但又不能偷懒简化。一开始我也只是用对话的方式丢给 AI 去查后来发现输出结果不稳定这次让它先查端口、下次它可能先查弱口令完全看模型当天心情。于是我把审计流程整理成了一套结构化的 Skill让模型严格按预定的步骤走输出格式也统一成一套模板。这篇内容就把我这个security-audit-skill从设计思路、模块拆分、代码编写到集成使用完整拆一遍。对安全工程师、运维、后端开发以及正在研究 Agent Skill 怎么落地到实际业务的同学应该都能直接抄作业。1. 为什么要专门做一个安全审计 Skill先说明一个概念这里说的 Skill 到底是个什么东西它跟最近流行的大模型 Agent、插件到底有什么区别。有些同学可能已经被这些词绕晕了。1.1 Skill 是什么它和 Agent、插件有什么区别我习惯用一个生活化的类比Agent 像是一个厨师它需要自己决定今天做什么菜、用什么锅、按什么顺序下料而 Skill 更像是一本菜谱它不负责决定做什么但它规定了某一类菜必须按照固定的步骤来做做出来之后摆盘也要按照规定来。放到技术场景里Skill 的本质就是一套「结构化的操作手册 可执行的工具描述」。它通常包含一个主描述文件比如 SKILL.md、若干辅助脚本、规则模板、输出模板。这套文件给 LLM 提供了明确的执行指引什么时候触发、按什么顺序执行、每一步该做什么、最后输出成什么格式。对比插件PluginSkill 更侧重于「教模型怎么做事情」而不是「扩展模型的外部能力」两者也可以配合使用。对比通用 AgentSkill 牺牲了灵活性换来了输出的稳定性和可复现性。我之所以用 Skill 而不是直接靠对话去让 AI 做安全审计核心原因就是稳定性。安全审计这件事步骤错了结论就错了不能接受模型自由发挥。1.2 安全审计场景里让我头疼的几个痛点先说一下我在实际做系统安全审计时经常遇到的几个问题我相信做一线安全的同学都会感同身受第一审计流程不统一。同一个团队里不同的人做审计思路完全不同。有的人先做端口扫描有的人先看中间件版本最后交上来的报告格式五花八门有的用 Word有的用 Excel还有直接在聊天记录里丢几行结论。这对后续追踪整改非常不友好。第二漏项问题严重。人工审计非常依赖个人经验和当时的状态。连续审三套系统到第三套的时候注意力明显下降很容易漏掉某个中间件漏洞或者某个错误配置。安全审计是一个「宁可多查、不可漏查」的工作漏掉一个高风险项前期的努力基本白费。第三重复劳动太多。资产信息收集、配置基线核查、CVE 版本比对——这些工作本身技术含量并不算高但很耗时。如果每套系统上线前都要人工重复一遍时间成本完全不可控。第四新手门槛高。安全审计涉及的知识面很广网络、系统、应用、数据库各个层面多少都要懂。团队里新同学想上手光是搞清楚「第一步要干什么」就得花不少时间。如果有了一套 Skill让 AI 带着流程执行新人就能顺着流程边做边学既不会漏步骤也能通过观察 AI 的输出逐步理解审计逻辑。1.3 这套 Skill 解决什么问题把审计流程标准化和自动化。目前这套security-audit-skill聚焦在四个方向资产信息收集、配置基线核查、已知漏洞识别、日志异常分析。它可以把这些步骤固定下来让 LLM 按照既定流程自主完成大部分审计操作并输出统一格式的报告。它适合这几类人安全工程师希望把重复性审计工作交给 AI 处理自己聚焦在结果研判和高危漏洞处置上。运维和开发需要在上线前快速做一个自我安全检查提前发现问题。在研究 Agent Skill 落地的同学这份内容也是一份完整的从 0 到 1 的 Skill 设计案例。2. Skill 整体架构与设计思路接下来我把这个 Skill 是怎么设计的拆开讲。重点不在于代码本身而是背后的设计逻辑。2.1 SKILL.md 的主文件结构一个标准 Skill 的核心是SKILL.md。这个名字不是随便起的很多 Agent 框架会自动扫描指定目录下的SKILL.md作为入口文件所以遵守约定比搞创新重要得多。我的SKILL.md分为几个部分YAML 元信息frontmatter包括name、description、when_to_use、version、tags等字段相当于这个 Skill 的身份证让模型能够快速判断「当前对话是否应该触发这个 Skill」。审计流程定义分阶段描述每个步骤需要做什么是 Skill 的主体。我会按「准备 - 收集 - 核查 - 分析 - 输出」的顺序组织。工具与脚本说明列出 Skill 依赖哪些外部命令或脚本比如nmap、curl、Python 脚本等以及它们的调用方式。输出规范强制要求明确输出报告的结构、字段、风险等级标准这是保证结论可读性和可对比性的关键。这样设计的好处是模型在执行时并不是自由发挥而是像拿到了一张「剧本」。每一步都有依据每一步都有产出物。2.2 模块化设计审计流程拆成五个阶段我在设计时把安全审计流程拆成了五个阶段资产信息收集确定审计目标的 IP、域名、端口、服务、中间件版本。配置基线核查对照安全基线检查常见配置项。漏洞与风险识别基于版本信息和指纹数据识别已知 CVE 及高危风险。日志与异常分析分析审计对象产生的日志查找异常行为。报告输出把前几步结果汇总成结构化报告。这五个阶段对应了审计的完整闭环。把这些阶段固化到 Skill 里模型每次执行都能按照同样的路径走结果可对比、可追溯。模块化还有一个实际好处如果某个阶段需要更新规则只改对应的部分就行不用动整个流程。比如 CVE 库更新了只需要替换漏洞比对模块的参考数据不影响其他环节。2.3 设计原则审计工单式、可追溯、可复现在写这个 Skill 之前我给自己定了三个设计原则。第一审计工单式。每次审计必须有一个任务编号格式比如AUDIT-{日期}-{序号}所有步骤的记录都和这个编号关联。这样后续追溯的时候能知道这次审计发生在什么时候、覆盖了哪些目标、执行了哪些检查。审计工作最忌讳「做完了说不清做了什么」。第二可追溯。审计过程中的关键数据比如扫描命令的原始输出、配置文件的具体路径、漏洞比对的依据版本都要求保留在审计记录中。AI 给出的每一个结论都要能指出「我是根据什么得出这个结论的」避免出现「模型说有问题但说不出哪里有问题」的尴尬局面。第三可复现。同样一套规则跑同样的目标得到的结果应该一致。这就要求 Skill 里的检查项都是确定性的比如「检查 Nginx 配置里是否包含 X-Frame-Options 响应头」这个判断标准是唯一的而不是「大概看一下安全配置」那种模糊指令是审计大忌。3. 核心模块实现与实操细节这一部分进入正题把五个阶段里每一个模块的实现细节讲透并且给出必要的参数选择和计算逻辑方便你直接照搬到自己的 Skill 里。3.1 资产信息收集模块这个模块的目标是回答一个基本问题我在审计什么如果连目标对象都不清楚后面的核查和漏洞识别全都没有意义。具体到操作层面我会让 Skill 按以下顺序执行读取用户给出的审计目标可能是一个域名、一段 IP 段或者是一个具体的 URL。如果目标是域名先做 DNS 解析获取 IP 列表。这一步可以调用dig或nslookup命令。对解析到的 IP使用端口扫描工具识别开放的端口和对应服务。常用的命令是nmap -sV -p- --min-rate2000 target其中-sV表示做版本探测-p-表示扫描全部 65535 个端口。对识别出来的 HTTP/HTTPS 服务使用curl -I获取响应头提取Server字段、X-Powered-By字段这些信息是后续识别中间件类型和版本的关键。为什么端口扫描要加--min-rate2000因为安全审计面对的是自己的资产追求的是效率在你确认了目标归属之后提高发包速率可以大幅缩短扫描时间。如果是在做渗透测试往往会放慢速度来规避防护设备的拦截但审计场景不需要考虑这个。资产收集阶段得到的全部信息要求追加写入到审计记录文件里比如audit_assets.txt。这一步非常重要后面模块的所有判断都以这份资产清单为基础。3.2 配置基线核查模块配置基线核查本质上就是把目标系统当前的实际配置和安全基线逐条做对比。基线可以理解为「一套公认的安全配置下限」低于这个配置就视为不合规。在这个模块里我整理了常见的高频检查项。这里列一个简表方便你理解检查对象检查项期望值不合规风险SSH 服务是否允许 root 密码登录禁止或使用密钥登录暴力破解风险Nginx/Apache是否启用 HTTPS 并配置 HSTS是中间人攻击Web 响应头X-Frame-OptionsSAMEORIGIN或DENY点击劫持风险Web 响应头Content-Security-Policy存在且配置合理XSS 风险数据库默认端口是否修改视业务而定易被批量扫描数据库账号是否使用弱口令禁用弱口令数据泄露这个模块的执行方式我建议优先使用脚本自动检查而不是让 AI 自己去猜。因为 AI 读取配置文件是存在随机性的而脚本的执行结果是确定性的。比如在 Skill 里内置一个check_web_headers.py输入 URL输出响应头列表再由 AI 基于响应头列表判断是否合规。这种方式把「数据获取」和「逻辑判断」分离让 AI 专注于它更擅长的判断部分。3.3 漏洞与风险识别模块漏洞识别是整个 Skill 里风险最高的部分也是我最强调边界的一个模块。这里说的识别主要指两类第一类是基于版本信息的已知漏洞比对。从资产收集阶段拿到中间件的精确版本号然后在 CVE 数据库中检索该版本是否存在已知漏洞。这个过程可以用离线数据也可以调用在线漏洞库的 API。在我的 Skill 实现里我建议把常用中间件的 CVE 清单整理成一个本地 JSON 文件Skill 通过脚本查表这样不依赖外部网络环境稳定可控。第二类是基于配置和指纹的风险判断。某些场景下没有直接的 CVE 编号但配置明显引发风险隐患。比如检测到管理后台暴露在公网、用户上传目录允许执行脚本、返回头中泄露了绝对路径——这些都属于「配置类风险」。这类风险通常用规则引擎判断比较合适。这里要特别强调边界安全审计 Skill 做的是识别和验证不是利用。所有检查必须是非破坏性的。判定漏洞存在后不应该试图进行实际攻击或深度验证比如尝试上传恶意文件、执行探测性 payload这类操作应该留给专业的渗透测试工具去完成。3.4 日志与异常分析模块日志分析是安全审计里最费眼神的部分但也是 AI 最擅长辅助的部分。人看日志容易疲劳模型扫日志可以快速找出规律异常。我设计的流程是先由 AI 读取指定路径的日志文件然后按维度做聚合统计再针对异常指标做深入分析。常用的分析维度包括登录失败次数如果同一个来源 IP 在一小段时间内触发大量登录失败基本可以判定是暴力破解行为。异常时间点访问比如凌晨 3 点后台接口出现高频访问值得警惕。异常 User-Agent爬虫、扫描器、自动化攻击工具往往带有明显的 UA 特征。超大响应状态码占比某个时间段 4xx/5xx 状态码突然飙升可能是攻击行为或系统异常。在这个模块的实际实现中我会让 AI 先运行一个parse_logs.py脚本脚本负责把日志解析成结构化字段时间、IP、方法、路径、状态码、UA并输出 top N 统计表。AI 再基于统计表做语义层面的判断。这里的核心思路还是「脚本负责量模型负责质」两者配合效率最高。3.5 报告生成模块审计结果如果没有报告那审计就等于没做。报告模块定义了输出内容的结构这一步直接决定了下游整改能不能顺利推进。我在 Skill 里强制规定的报告结构如下审计概况任务编号、审计时间、审计目标、执行人或执行模型版本。资产清单摘要发现的开放端口、服务类型、中间件版本。风险发现列表每条发现包含风险描述、影响对象、风险等级、判断依据。整改建议针对每个风险给出可操作的建议。附录与原始记录所有脚本输出的原始数据留存。风险等级我统一采用三档高危、中危、低危。判断标准是可能导致数据泄露或服务被控制的问题定为高危可能在特定条件下被利用的定为中危仅增加攻击面、但暂时无法直接利用的问题定为低危。报告输出的默认格式是 Markdown方便在 Git 仓库里直接归档和审阅。如果团队有需要也可以让 Skill 一键转成 CSV 或 HTML。4. 从 0 到 1 编写自己的 security-audit-skill理论都清楚了现在就动手搭一个最小可用的实现。为了演示方便我以一个「单域名 Web 应用上线前的安全审计」为场景演示完整流程。4.1 初始化目录结构先建一个项目目录推荐的结构长这样security-audit-skill/ ├── SKILL.md ├── scripts/ │ ├── collect_assets.sh │ ├── check_web_headers.py │ └── parse_logs.py ├── data/ │ └── cve_list.json └── templates/ └── audit_report_template.md如果是要接入 Claude Code 这类支持自定义 Skill 目录的工具一般需要放在指定的 skills 目录下并把SKILL.md放在每个 skill 子目录的根上。下面我写的SKILL.md是核心所有逻辑都从它开始。4.2 编写 SKILL.md 主描述文件这个文件直接决定模型能不能正确理解并执行整个审计流程。元信息要简洁准确描述要让模型在多种场景下都能正确触发这个 Skill。下面是简化版的核心内容--- name: security-audit-skill description: 面向 Web 应用和业务系统的上线前安全审计覆盖资产发现、配置基线核查、已知漏洞识别、日志异常分析和审计报告生成。当用户要求进行安全审计、系统安全检查、上线前排查时调用。 version: 1.0.0 tags: [security, audit, pentest-baseline] --- # Security Audit Skill ## 审计前置要求 1. 确认用户提供了有效的审计目标域名 / IP / URL。 2. 询问目标归属确认用户有权对该资产进行安全审计。 3. 为本次审计生成一个任务编号格式AUDIT-YYYYMMDD-序号。 4. 每次审计开始时创建独立的审计记录目录。 ## 执行流程 ### 第一步资产信息收集 - 运行 scripts/collect_assets.sh target获取 DNS 解析结果、开放端口与服务版本。 - 对开放的 HTTP/HTTPS 服务运行 curl -I 获取响应头信息。 - 将资产信息保存到审计记录目录的 assets.txt。 ### 第二步配置基线核查 - 读取 assets.txt 中的服务信息。 - 对 Web 服务运行 scripts/check_web_headers.py url检查安全响应头。 - 逐条核对配置基线表见 data/baseline_rules.md记录不合规项。 ### 第三步漏洞与风险识别 - 从 assets.txt 提取中间件与版本号。 - 使用 data/cve_list.json 进行版本比对记录命中项。 - 对高危版本结合业务场景给出可利用性初步判断。 ### 第四步日志与异常分析 - 如果用户提供日志目录运行 scripts/parse_logs.py log_dir。 - 分析登录失败、异常时间访问、异常 UA、状态码突增四类指标。 ### 第五步报告输出 - 使用 templates/audit_report_template.md 生成报告。 - 每条风险必须包含现象、证据、风险等级、整改建议。 - 报告输出到审计记录目录的 report.md。这份SKILL.md的关键在于两个地方一是元信息部分使用description字段告诉模型什么场景下触发二是执行流程部分把每一步该运行什么脚本、输出什么文件都写清楚了。模型按图索骥就不会乱来。4.3 编写一个核心检查脚本这里我以响应头检查脚本为例直接展示一个能跑的版本。它的作用是输入一个 URL输出安全响应头检查结果并附带风险说明import requests import sys SECURITY_HEADERS { X-Frame-Options: {good_value: None, risk: 点击劫持}, Content-Security-Policy: {good_value: None, risk: XSS 注入面过大}, Strict-Transport-Security: {good_value: None, risk: HTTPS 降级风险}, X-Content-Type-Options: {good_value: nosniff, risk: MIME 嗅探}, } def check_headers(url): try: resp requests.get(url, timeout10, verifyFalse, allow_redirectsTrue) except Exception as exc: print(f[ERROR] 无法访问目标: {exc}) sys.exit(1) print(f[*] 目标 URL: {resp.url}) print(f[*] 状态码: {resp.status_code}) print(f[*] Server: {resp.headers.get(Server, 未识别)}) print() issues [] for header, cfg in SECURITY_HEADERS.items(): value resp.headers.get(header) if value is None: issues.append((header, 缺失, cfg[risk])) print(f[FAIL] {header}: 缺失 — 风险: {cfg[risk]}) elif cfg[good_value] and cfg[good_value] not in value: issues.append((header, value, cfg[risk])) print(f[WARN] {header}: {value} — 建议包含 {cfg[good_value]}) else: print(f[PASS] {header}: {value}) print() if issues: print(f[*] 共发现 {len(issues)} 个响应头配置问题) else: print([*] 响应头配置检查全部通过) if __name__ __main__: if len(sys.argv) ! 2: print(用法: python check_web_headers.py url) sys.exit(1) check_headers(sys.argv[1])这段脚本很简单但用在审计里很顺手。它把检查结果分成FAIL、WARN、PASS三档模型拿到输出后可以直接把这些结果映射到报告模板中。注意这里特意用了verifyFalse因为审计目标有时是内部测试环境证书可能不合法这个参数可以在内网环境里避免证书校验报错。如果在生产环境使用请去掉这个参数并完善证书处理。4.4 将 Skill 接入主流工具现在大部分支持 Skill 的 Agent 工具都遵循类似的接入方式。以 Claude Code 为例它会把 Skill 放置在项目的.claude/skills/目录下每个 Skill 独立目录中包含SKILL.md和关联文件。你只需要把上面的目录整体复制进去即可。如果是 OpenCode 或 Codex它们的 Skill 目录命名和加载机制略有差异但核心都是让SKILL.md被正确扫描到。实际接入后的调用效果类似这样# 在 Agent 环境中直接输入审计诉求 请对 https://staging.example.com 进行一次安全审计并生成报告模型读取到security-audit-skill的元信息后如果认为匹配就会进入主动引导流程确认目标归属、生成任务编号、执行资产收集脚本、逐模块校验并输出最终报告。整个过程中你基本上只需要回答确认性问题以及最后审核报告。4.5 测试与迭代策略第一次写完 Skill 后不要直接拿生产系统去试很容易被自己的半成品坑到。我的建议是找一套测试环境或者直接用本地启动的容器应用来验证。测试时重点检查这几件事模型能不能在合适的场景下自动触发 Skill。每个脚本在目标环境里是否都能正常运行并输出结构化结果。报告模板能否完整填充是否存在空缺字段。多次运行同一目标报告结果是否一致有没有随机漏项。初版跑通后再逐步扩充检查规则。比如先在cve_list.json里只放 Nginx、Apache、Tomcat 三个常用组件的数据跑通了再扩展到 Redis、MySQL 等。5. 实际使用中遇到的问题与排查这个 Skill 写了之后我在自己团队内部和几个朋友那里都测试过踩了不少坑。这里整理下最常见的问题和排障思路价值不比上面的代码少。5.1 常见问题速查现象可能原因解决方案模型不触发 Skill直接当普通对话处理description元信息里的关键词覆盖不足在description中补充「系统安全检查、上线前评估、配置核查」等触发词审计过程卡在资产收集阶段collect_assets.sh缺少执行权限或依赖的扫描工具未安装给脚本添加执行权限检查环境依赖报告输出内容太浅没有具体证据在执行流程中缺少强制输出证据的要求在SKILL.md中明确要求每条风险必须附带「证据字段」AI 自由发挥跳过某些模块流程描述里的步骤顺序不够强约束将流程描述改为「必须严格按顺序执行不允许跳过」必要时在阶段间引入确认节点多个 Skill 被同时触发互相干扰Skill 间description职责重叠精简元信息每个 Skill 聚焦一类场景必要时设置排除条件5.2 几个很关键的避坑经验第一不要试图让一个 Skill 覆盖所有审计场景。我一开始也试着把 Web、主机、容器、数据库的审计全塞进一个 Skill 里结果模型执行时经常串台在查 Web 响应头的时候突然跳到检查 MySQL 权限。后来我把它们拆成两个独立 Skill比如web-audit-skill和host-audit-skill每个只专注一件事触发准确率大幅上升。所以这套security-audit-skill核心聚焦 Web 应用其他场景可以自行衍生。第二命令输出太长会严重影响模型判断。资产扫描可能产生几百上千行结果全丢给模型它不仅容易遗漏关键信息还会增加 token 消耗。正确做法是在脚本里做好摘要让脚本只输出模型判断需要的高价值信息比如服务名、版本号、开放端口列表、高危配置项列表而不是原始全量输出。第三AI 审计报告的审核不能省。再好的 Skill模型也会有误判的可能尤其是风险等级评定部分。模型对「业务影响」的理解是有限的一个在技术上高危的漏洞如果业务上根本没有暴露到公网它可能不会做这种语境判断。所以 AI 生成的报告必须有一个人工复核环节。我的处理方式是让 Skill 在报告末尾加一个「待人工复核清单」把所有涉及高危风险的条目单独列出来方便我逐个确认。第四注意审计范围控制。Skill 执行过程中会主动向目标发送探测请求这类操作最好先获得授权并且控制扫频率、控制在测试环境或自有资产范围内。在生产环境做审计时扫描工具的并发量级、执行的探测脚本都要按生产变更流程把控不能拿审计当借口随手跑激进命令。6. 这个 Skill 后续还能怎么扩展目前这套security-audit-skill已经能覆盖大部分 Web 应用上线前的常规安全自查但我自己还在持续迭代。这里分享几个我接下来打算做的方向也让有需要的同学有个参考。可以增加定时巡检模式把 Skill 接到 CI/CD 流水线上每次构建后自动触发一次基础安全扫描再配合告警系统把高危问题直接推给相关负责人。也可以扩展 Snort/Suricata 之类的安全设备日志分析模块让 Skill 能够处理更上层的威胁告警信息。另外一个比较有价值的方向是引入合规化报告支持。现在很多行业都明确要求定期做安全评估如果 Skill 能够把审计结果按照技术报告的标准格式输出那就可以直接作为报告附件使用省去大量整理工作。我对这个实践最深的体会是Skill 的功夫不在代码而在流程设计。代码只是把流程固化的工具。你只要把「标准审计流程」想清楚把它翻译成模型能理解的分步指令和明确的输出规范这个 Skill 就成功了一半。越是经验丰富的老手越容易在这一步做出高质量的 Skill因为你的行业经验本身就是最核心的资产。以后我自己再遇到重复性的安全运维工作第一反应绝对是从日常经验里提炼成 Skill而不是临时去翻工具书或者让 AI 自由发挥。这个习惯给我省下的时间和精力确实远超我当初搭建这套框架所投入的成本。