name: code-security-audit
description: 基于中国国家标准(GB/T 34943/34944/34946/39412)的代码安全审计工具。支持 Java、C/C++、C#、Python 多语言漏洞检测,采用「快速扫描 + LLM 深度审计」双引擎,自动去重生成的 Markdown 格式审计报告。适用于项目验收、安全合规审查、代码质量评估等场景。
> 测试环境:已在 GLM-5 模型下测试通过
>
> 详细文档:
> - 详细审计流程 - LLM 审计执行流程和验证机制
> - 输出质量检查标准 - 修复方案编写要求和验证机制
> - 常见问题解决方案 - 问题排查指南
> - 漏洞知识库 - 各类漏洞的危险模式与修复方案
> - 国标规则文件 - GB/T 34943/34944/34946/39412 完整规则
本技能提供完整的代码安全审计工作流,基于中国国家标准检测源代码中的安全漏洞。
核心流程:
快速扫描 → 基线入库 → LLM 深度审计 → 生成报告
输出物:
findings/baseline/*.md — 快速扫描发现的漏洞
findings/llm_audit/*.md — LLM 独立审计发现的漏洞
audit_report_YYYYMMDD_HHMMSS.md — 最终审计报告
根据审计结果,正确的分工应该是:
| 分工 | 负责方 | 发现的漏洞类型 | 检出率 |
|------|--------|---------------|--------|
| 快速扫描 | 代码(正则表达式) | 高风险函数调用 | ~64% |
| LLM审计 | LLM(语义分析) | 需要上下文分析的漏洞 | ~61% |
| LLM审查 | LLM(深入分析) | 复杂业务逻辑、漏洞验证 | 最高 |
职责:使用正则表达式搜索高风险函数,发现高风险函数调用
⚠️ 重要说明:快速扫描规则已在 scripts/skill.py 的 quick_scan_patterns() 函数中定义,LLM 审计不应重复这个工作。
特点:
scripts/skill.py 第 319-420 行
职责:语义分析,发现需要上下文分析的漏洞
⚠️ 重要说明:LLM审计应专注于需要上下文分析的漏洞,不应使用关键字搜索。
特点:
audit_workflow.md
职责:深入分析复杂业务逻辑,验证漏洞,做出最终决策
特点:
| 验证项 | 说明 | 工具函数 |
|--------|------|---------|
| 必填字段完整性 | baseline检查12个字段,LLM审计检查13个字段(含修复方案) | validate_required_fields() + LLM_REQUIRED_FIELDS |
| 国标映射格式 | 检查国标映射格式是否正确 | validate_gbt_mapping() |
| 代码片段/行号 | 验证代码片段和行号准确性,含自动修正 | validate_code_snippet() |
| 问题描述格式 | 检查字数≥20,不重复代码片段 | validate_description_format() |
| 修复方案格式 | 检查字数≥20 | validate_fix_format() |
代码特点:
| 质量项 | LLM判断要点 | 重要性 |
|--------|------------|--------|
| 问题描述内容 | 是否说明了漏洞原因、攻击方式、潜在风险 | 🔴 高 |
| 修复方案内容 | 是否具体、合理、可行;是否包含代码示例或API建议 | 🔴 高 |
| 严重等级 | 是否符合漏洞实际危害(考虑上下文、可利用性、影响范围) | 🟠 中 |
| 误报判定 | 是否有安全防护、是否仅导入无调用、是否测试代码 | 🟠 中 |
LLM质量判断要求:
LLM责任:
代码辅助功能:
validate_code_snippet() 会自动修正错误的行号
工作流程:
LLM创建md文件 → finalize_report 自动验证 →
如果行号错误:
代码自动修正行号 → 状态设为"有效"
如果验证失败:
记录为幻觉 → 不出现在报告中
违反后果:
LLM 审计相比传统静态分析工具具有独特优势,必须充分利用:
| 优势 | 说明 | 检查方法 |
|------|------|----------|
| 语义理解 | 理解代码意图,不只是模式匹配 | 分析变量用途、函数语义 |
| 跨文件调用链 | 追踪数据流和控制流跨多个文件 | Grep 搜索调用点,Read 查看上下文 |
| 业务逻辑漏洞 | 理解业务场景发现逻辑缺陷 | 分析认证流程、权限判断、状态转换 |
| 上下文关联 | 关联变量、函数、类之间的关系 | 分析数据来源、传递路径、使用场景 |
| 组合漏洞 | 发现多个弱点组合形成攻击链 | 分析:注入 + 权限绕过 + 信息泄露 |
| 定制风险 | 根据项目特点发现特定安全问题 | 分析框架特性、API 设计、配置风险 |
LLM 审计应发现的典型问题(传统工具难以检测):
审计检查技巧:
🔴 强制执行:LLM 在执行审计前必须完整阅读以下文档:
违反后果:未阅读上述文档将导致审计不完整、遗漏关键漏洞、行号错误、质量不合格等问题。
⚠️ 极其重要:行号错误会导致验证逻辑错误修正,报告中显示错误位置,严重影响审计可信度。
步骤 1:使用 Grep 精确搜索
# 搜索函数定义
Grep pattern="def auth_bypass" path="目标文件" output_mode="content" -n
# 搜索类定义
Grep pattern="class VulnerableClass" path="目标文件" output_mode="content" -n
# 搜索变量声明
Grep pattern="HARDCODED_PASSWORD" path="目标文件" output_mode="content" -n
步骤 2:确认行号对应实际代码
步骤 3:填写验证后的精确行号
| 错误类型 | 错误示例 | 正确做法 |
|---------|---------|---------|
| 凭记忆填写 | 行号: 164(实际在185) | 使用 Grep 验证后填写 |
| 关键词推断 | 根据函数名推断位置 | 使用 Grep 精确搜索 |
| 注释行号 | 行号指向注释而非代码 | 确认行号对应实际代码 |
finalize_report 的验证逻辑使用关键词匹配:
def + self 就会被错误匹配
错误修正示例:
原始行号: 185 (auth_bypass函数)
验证逻辑关键词匹配: def + self → 匹配到第32行
错误修正后: 行号变成32
报告显示: 错误位置
发现漏洞 → Grep搜索精确位置 → 确认行号 → 创建md文件 → finalize_report验证通过
理论上支持所有编程语言的代码安全审计。
| 语言类型 | 适用标准 | 映射格式 |
|----------|----------|----------|
| 有专用标准(双映射) | 专用标准 + GB/T 39412-2020 | GB/T349XX-规则;GB/T39412-规则 |
| Java | GB/T 34944-2017 + GB/T 39412-2020 | GB/T34944-6.2.3.3;GB/T39412-6.1.1.6 |
| C/C++ | GB/T 34943-2017 + GB/T 39412-2020 | GB/T34943-6.2.3.6;GB/T39412-8.2.6 |
| C# | GB/T 34946-2017 + GB/T 39412-2020 | GB/T34946-6.2.3.3;GB/T39412-6.1.1.6 |
| 无专用标准(单映射) | 仅 GB/T 39412-2020 | GB/T39412-规则 |
| 其他语言 | GB/T 39412-2020 | GB/T39412-{适用规则} |
> 详细规则见国标文件:
> - GBT_34943-2017.md - C/C++ 专用
> - GBT_34944-2017.md - Java 专用
> - GBT_34946-2017.md - C# 专用
> - GBT_39412-2020.md - 通用基线(所有语言)
🔴 强制要求:此步骤必须输出确认信息,否则不应继续后续步骤。
【步骤 2 学习标准确认】
- 已阅读:audit_workflow.md(审计执行流程)
- 已阅读:quality_standards.md(质量检查清单)
- 已学习:国标规则 X 条(语言:Java/C++/Python/...)
- 已理解:质量检查清单 5 项
- 已理解:修复方案要求(字数≥30,禁止敷衍内容)
- 下一步:步骤 3 - 创建目录
| 文档 | 学习要点 |
|------|---------|
| audit_workflow.md | 四轮审计流程、漏洞类型清单、行号验证方法 |
| quality_standards.md | 质量检查清单、修复方案要求、禁止行为 |
| 国标规则文件 | 根据语言选择对应国标,学习规则编号和描述 |
┌─────────────────────────────────────────────────────────────────────┐
│ Agent 代码安全审计流程 │
├─────────────────────────────────────────────────────────────────────┤
│ 0️⃣ 学习流程 ◀ 【强制】阅读 SKILL.md + audit_workflow.md + quality_standards.md │
│ 1️⃣ 语言判定 ◀ 【LLM 自主】通过文件扩展名判断语言 │
│ 2️⃣ 创建目录 ◀ 【必须】创建 findings/baseline 和 llm_audit 目录 │
│ 3️⃣ 快速扫描 ◀ 【自动】调用 quick_scan,直接生成 baseline md 文件 │
│ 4️⃣ 学习标准 ◀ 【必须输出】确认已学习的国标及规则数 │
│ 5️⃣ LLM 审计 ◀ 【必须】多 agent 并行审计 + 创建 md │
│ 6️⃣ 生成报告 ◀ 【必须调用 finalize_report】去重 + 验证 + 生成 │
│ 7️⃣ 审计完成 ◀ 【输出】报告路径和验证结果 │
└─────────────────────────────────────────────────────────────────────┘
💡 流程设计说明:
⚠️ 步骤 0 强制要求:
⚠️ 此步骤自动完成,无需 LLM 参与:
步骤 4:快速扫描(自动)
┌─────────────────────────────────────────────────────────────────────┐
│ ThreadPoolExecutor 并行扫描所有代码文件 │
│ ┌──────┬──────┬──────┬──────┬──────┬──────┬──────┬──────┐ │
│ │文件1 │文件2 │文件3 │文件4 │文件5 │文件6 │文件7 │文件8 │ ← 按文件 │
│ │扫描 │扫描 │扫描 │扫描 │扫描 │扫描 │扫描 │扫描 │ 并行 │
│ └──────┴──────┴──────┴──────┴──────┴──────┴──────┴──────┘ │
└─────────────────────────────────────────────────────────────────────┘
↓
生成 baseline md 文件(状态默认为"误报")
执行方式:
quick_scan --target 命令
⚠️ 此步骤需要 LLM 参与,推荐多 agent 并行处理:
┌─────────────────────────────────────────────────────────────────────┐
│ 步骤 5 LLM审计流程 │
├─────────────────────────────────────────────────────────────────────┤
│ ⚠️ 强制要求:必须审计全部代码文件(详见 audit_workflow.md) │
│ 5a:独立审计全部代码文件(不查看 baseline md 文件) │
│ 5b:多 agent 并行审计 + 状态判定 + 创建 llm_audit md 文件 │
└─────────────────────────────────────────────────────────────────────┘
🔴 强制要求:LLM审计必须覆盖项目中的全部源代码文件,不得遗漏任何文件。
原因说明:
执行方法:
# 1. 使用Glob获取全部代码文件列表
Glob path="项目目录" pattern="**/*.java" # Java项目
Glob path="项目目录" pattern="**/*.py" # Python项目
# 2. 逐个阅读并审计每个文件
Read file_path="文件1路径" limit=200
Read file_path="文件2路径" limit=200
...
# 3. 发现漏洞后创建llm_audit md文件
Write file_path="findings/llm_audit/xxx.md" content="..."
> � 详细检查清单:见 audit_workflow.md "LLM审计详细检查清单"章节
⚠️ 推荐多 agent 并行处理,提升效率:
步骤 5b:按批次并行审计(LLM)
┌─────────┬─────────┬─────────┬─────────┐
│ Agent 1 │ Agent 2 │ Agent 3 │ Agent 4 │ ← 多 agent 并行审计
│ 批次 1 │ 批次 2 │ 批次 3 │ 批次 4 │
│ 文件1-20│文件21-40│文件41-60│文件61-80│
└─────────┴─────────┴─────────┴─────────┘
↓
合并结果 → 进入步骤 6
分批策略:
| 策略 | 说明 | 适用场景 |
|------|------|----------|
| 按数量分批 | 每批 20-30 个文件 | 通用场景 |
| 按语言分批 | 每个 agent 处理一种语言 | 多语言项目 |
| 按漏洞类型分批 | 每个 agent 处理一类漏洞 | 漏洞类型集中 |
并行处理要求:
| 判定规则 | 特征 | 状态 | 示例 |
|---------|------|------|------|
| 仅导入语句 | 只有 import/using,无实际调用 | 误报 | import subprocess 但未使用 |
| 测试/演示代码 | 位于 test/demo 目录或含测试注解 | 误报 | @Test, def test_xxx() |
| 安全的使用方式 | 有 sanitization/白名单校验 | 误报 | 参数经白名单过滤后的 exec |
| 实际危险调用 | 直接使用危险 API 无防护 | 有效 | Runtime.exec(userInput) |
| 硬编码密码 | 密码/密钥直接写在代码中 | 有效 | password = "admin123" |
| 弱加密算法 | 使用 DES/MD5/SHA1 等 | 有效 | Cipher.getInstance("DES") |
┌─────────────────────────────────────────────────────────────────────┐
│ 单个发现状态判定流程 │
├─────────────────────────────────────────────────────────────────────┤
│ ⚠️ 必须使用 Read 工具检查代码上下文(前后 10 行) │
│ 1️⃣ 检查是否仅导入 ◀ 是 → 保持"误报" │
│ 2️⃣ 检查是否测试代码 ◀ 是 → 保持"误报" │
│ 3️⃣ 检查是否有安全防护 ◀ 是 → 保持"误报" │
│ 4️⃣ 检查是否实际危险调用 ◀ 是 → 改为"有效" │
│ 5️⃣ 更新 md 文件 ◀ 修改状态字段 │
└─────────────────────────────────────────────────────────────────────┘
必须使用工具检查,禁止凭记忆判定:
| 检查项 | 工具 | 说明 |
|--------|------|------|
| 本文件上下文 | Read | 读取发现行前后 10 行 |
| 跨文件调用 | Grep | 搜索项目范围内的实际调用 |
两项检查都必须执行:
Read 读取发现所在文件,检查前后 10 行上下文
Grep 搜索项目范围,检查实际调用
import pickle → 搜索 pickle.loads、pickle.load
import subprocess → 搜索 subprocess.run、subprocess.call
检查示例:
# 本文件上下文
Read file_path="发现所在文件" offset=行号-10 limit=20
# 跨文件调用检查
Grep pattern="pickle\.loads" path="项目目录"
Grep pattern="subprocess\.run" path="项目目录"
常见误报判定:
import 无调用 → 误报
代码仅做基本格式验证,以下质量判断由 LLM 负责:
| 质量项 | LLM 判断要点 |
|--------|--------------|
| 问题描述 | 是否说明了漏洞原因、攻击方式、潜在风险 |
| 修复方案 | 是否具体、合理、可行;是否包含代码示例或 API 建议 |
| 严重等级 | 是否符合漏洞实际危害(考虑上下文、可利用性、影响范围) |
| 误报判定 | 是否有安全防护、是否仅导入无调用、是否测试代码 |
问题描述要求:
修复方案要求:
baseline md 文件格式(快速扫描生成):
编号: #001
严重等级: 严重
漏洞类型: COMMAND_INJECTION
文件路径: test-samples/java/VulnerableJava.java
行号: 31
CWE: CWE-78
国标映射: GB/T34944-6.2.3.3 命令注入;GB/T39412-6.1.1.6 命令行注入 ◀ 【双国标映射】
来源: quick_scan
语言: java
状态: 误报 ◀ 【默认】LLM 审计时判定为"有效"或保持"误报"
问题代码: Runtime.getRuntime().exec(command);
问题描述: 描述内容(2-3句话)
llm_audit md 文件格式(LLM 审计创建):
编号: #001
严重等级: 严重
漏洞类型: COMMAND_INJECTION
文件路径: test-samples/java/VulnerableJava.java
行号: 31
CWE: CWE-78
国标映射: GB/T34944-6.2.3.3 命令注入;GB/T39412-6.1.1.6 命令行注入 ◀ 【双国标映射】
来源: llm_audit
语言: java
状态: 误报 ◀ 【默认】LLM 审计时判定为"有效"或保持"误报"
问题代码: Runtime.getRuntime().exec(command);
问题描述: 描述内容(2-3句话)
修复方案: 具体修复方法(≥20字)
> 状态字段规则:
> - 默认状态:所有 md 文件默认状态为"误报"
> - LLM 判定:LLM 审计时判定为"有效"或保持"误报"
> - 禁止写"待判定":状态字段必须填写(有效/误报)
> 双国标映射规则:
> - Java: GB/T 34944-2017 + GB/T 39412-2020
> - C/C++: GB/T 34943-2017 + GB/T 39412-2020
> - C#: GB/T 34946-2017 + GB/T 39412-2020
> - Python: 仅 GB/T 39412-2020(单映射)
>
> 格式:语言专用标准;通用基线,用中文分号分隔
⚠️ 此步骤自动完成,调用 finalize_report 命令:
┌─────────────────────────────────────────────────────────────────────┐
│ 步骤 6 生成报告流程 │
├─────────────────────────────────────────────────────────────────────┤
│ 6a:加载所有 md 文件(baseline + llm_audit) │
│ 6b:去重处理(按文件-行号-类型去重,被丢弃的 md 状态设为"重复") │
│ 6c:验证状态为"误报"的发现(代码片段验证 + 行号修正) │
│ 6d:验证通过 → 状态设为"有效";验证失败 → 记录幻觉 │
│ 6e:过滤状态不为"有效"的发现 │
│ 6f:生成报告(只包含"有效"状态的发现) │
└─────────────────────────────────────────────────────────────────────┘
| 验证项 | 说明 | 结果 |
|--------|------|------|
| 去重处理 | 按 file:line:type 去重,LLM 审计优先 | 去重后的发现列表 |
| 重复标记 | 被丢弃的 md 文件状态设为"重复" | 重复列表 |
| 验证范围 | 只验证状态为"误报"的发现 | 待验证列表 |
| 代码片段验证 | 验证代码片段是否存在于文件中 | 通过/失败 |
| 行号修正 | 如果行号不准确,修正为正确行号 | 修正后的行号 |
| 状态更新 | 验证通过 → 状态设为"有效" | 有效/幻觉 |
| 幻觉记录 | 验证失败的发现记录为幻觉 | 幻觉列表 |
⚠️ 报告的明细和统计只针对状态为"有效"的 md 文件:
| 内容 | 说明 |
|------|------|
| 漏洞明细 | 只包含状态为"有效"的发现 |
| 漏洞统计 | 只统计状态为"有效"的发现 |
| 严重等级分布 | 只统计状态为"有效"的发现 |
| 漏洞类型分布 | 只统计状态为"有效"的发现 |
| 语言分布 | 只统计状态为"有效"的发现 |
| 国标映射统计 | 只统计状态为"有效"的发现 |
finalize_report --output audit_report.md
{
"total_loaded": 加载的 md 文件总数,
"after_dedup": 去重后的数量,
"duplicates_count": 重复的数量,
"after_validation": 验证后的数量,
"hallucinations_count": 幻觉数量,
"effective_count": 有效发现数量(报告中的数量)
}
⚠️ 此步骤输出审计结果:
| 内容 | 说明 |
|------|------|
| 报告路径 | 生成的审计报告文件路径 |
| 验证结果 | 验证是否通过 |
| 有效发现数量 | 状态为"有效"的发现数量 |
| 幻觉数量 | 验证失败的发现数量 |
| 重复数量 | 去重时被丢弃的发现数量 |
⚠️ 强制要求:LLM 审计必须按照以下检查清单逐项执行,确保全面覆盖。
⚠️ 重要说明:此轮审计由快速扫描自动执行,LLM审计不应重复这个工作。
快速扫描已覆盖的漏洞类型:
LLM审计应跳过此轮,直接进入第二轮数据流分析。
必须完成的分析项:
必须完成的审计项:
必须完成的分析项:
必须完成的审计项:
必须达到的覆盖目标:
| 漏洞类型 | 目标覆盖 | 检查方法 |
|---------|---------|---------|
| 严重漏洞 | 100% | 检查清单中所有严重漏洞类型都已审计 |
| 高危漏洞 | 100% | 检查清单中所有高危漏洞类型都已审计 |
| 语言覆盖 | 100% | 所有检测到的语言都已审计 |
| 文件覆盖 | 100% | 必须审计全部代码文件,不得遗漏任何文件 |
> 🔴 使用时机:创建每个 md 文件时必须执行此检查
> 详细检查清单见 docs/workflow/quality_standards.md
> 详细禁止行为清单见 docs/workflow/quality_standards.md
> 详细确认清单见 docs/workflow/quality_standards.md
| 工具 | 描述 | 命令 |
|------|------|------|
| quick_scan | 快速扫描:正则 + Bandit/Semgrep/Gitleaks | python scripts/skill.py quick_scan --target |
| finalize_report | 收尾报告:去重 + 验证 + 生成 | python scripts/skill.py finalize_report [--output=...] |
finalize_report 验证内容:
| 验证项 | 说明 |
|--------|------|
| 去重处理 | 按 file:line:type 去重,LLM 审计优先 |
| 代码片段验证 | 验证代码片段是否存在于文件中 |
| 行号修正 | 如果行号不准确,修正为正确行号 |
| 状态更新 | 验证通过 → 状态设为"有效" |
| 幻觉记录 | 验证失败的发现记录为幻觉 |
| 修复方案 | 字数≥20 |
> 质量判断由 LLM 负责:问题描述是否说明漏洞原因/风险、修复方案是否合理可行
编号: #001
严重等级: 严重
漏洞类型: 命令注入
文件路径: test-samples/java/VulnerableJava.java
行号: 31
CWE: CWE-78
国标映射: GB/T34944-6.2.3.3 命令注入;GB/T39412-6.1.1.6 命令行注入 ◀ 【双国标】
来源: llm_audit
语言: java
问题代码: Runtime.getRuntime().exec(command);
问题描述: 描述内容(2-3句话)
修复方案: 修复内容(≥30字,含具体代码/命令/API)
> 国标映射格式:
> - 有专用标准的语言(Java/C/C++/C#):双映射,格式 {专用标准};GB/T39412-{规则}
> - 无专用标准的语言(Python/Go/JS/PHP/Rust等):单映射,格式 GB/T39412-{规则}
> - 分隔符使用中文分号 ;
> - GB/T 39412-2020 是通用标准,适用于所有语言
> 详细质量检查标准见 docs/workflow/quality_standards.md
> 详细禁止行为清单见 docs/workflow/quality_standards.md
> 详细流程和验证机制见 docs/workflow/audit_workflow.md
| 问题 | 解决方案 |
|------|----------|
| md 文件无法解析 | 使用英文冒号 : |
| 多值参数解析错误 | 多值参数用空格分隔 --languages java python |
| LLM 审计发现被过滤 | 使用 Grep 工具验证行号 |
> 详细问题解决方案见 docs/workflow/troubleshooting.md
⚠️ 说明:外部工具集成仅用于快速扫描阶段,LLM审计不应依赖外部工具结果。
| 工具 | 用途 | 集成方式 |
|------|------|----------|
| Gitleaks | 密钥/凭证检测 | 自动调用 |
| Bandit | Python 安全分析 | 自动调用 |
| Semgrep | 多语言模式匹配 | 自动调用 |
> 外部工具在快速扫描阶段自动调用,LLM审计应专注于语义分析和业务逻辑漏洞检测。
共 5 个版本