codeql

codeql

热门

利用 CodeQL 的过程间数据流与污点追踪分析能力,深度扫描代码库中的安全漏洞。当出现“run codeql”、“codeql scan”、“codeql analysis”、“build codeql database”或“find vulnerabilities with codeql”等指令时自动触发。支持“全量扫描”(包含 security-and-quality + security-experimental 查询集)与“仅看重点”(高置信度安全问题)扫描模式。同时支持创建数据扩展模型(Data Extension Models)并处理 CodeQL 的 SARIF 格式结果输出。

6367Star
548Fork
更新于 2026/8/1
SKILL.md
只读
名称
codeql
描述

利用 CodeQL 的过程间数据流与污点追踪分析能力,深度扫描代码库中的安全漏洞。当出现“run codeql”、“codeql scan”、“codeql analysis”、“build codeql database”或“find vulnerabilities with codeql”等指令时自动触发。支持“全量扫描”(包含 security-and-quality + security-experimental 查询集)与“仅看重点”(高置信度安全问题)扫描模式。同时支持创建数据扩展模型(Data Extension Models)并处理 CodeQL 的 SARIF 格式结果输出。

CodeQL 分析

支持的语言:Python, JavaScript/TypeScript, Go, Java/Kotlin, C/C++, C#, Ruby, Swift。

Skill 资源: 参考文件和模板位于 {baseDir}/references/{baseDir}/workflows/

核心原则

  1. 数据库质量是硬指标。 能成功编译构建的数据库,并不意味着质量达标。务必运行质量评估(检查文件数量、基线代码行数 LoC、提取器报错),并与预期源码文件做对比。如果是纯缓存构建,提取出的有用信息基本为零。

  2. 数据扩展(Data Extensions)能补齐 CodeQL 遗漏的盲区。 即便是使用标准框架(Django、Spring、Express)的项目,通常也有针对数据库调用、请求解析或 Shell 执行的自定义封装。如果跳过创建数据扩展工作流,就会漏掉项目专属代码路径中的漏洞。

  3. 显式引用查询集(Suite),防止查询规则被默默过滤。 切勿将 pack 名称直接传给 codeql database analyze —— 每个包自带的 defaultSuiteFile 会施加隐藏过滤规则,可能导致最终跑出 0 个结果。务必生成自定义的 .qls 查询集文件。

  4. 零漏洞需要排查,而不是庆祝。 扫描出 0 个结果,可能意味着数据库构建质量差、缺少数据模型、选错了查询包,或者是查询集被静默过滤了。在出具“代码安全”结论前,一定要排查清楚。

  5. macOS Apple Silicon 编译型语言需要特殊变通方案。 出现退出码 137 是因为 arm64e/arm64 架构不匹配,并不是构建本身失败。在退而求其次使用 build-mode=none 前,请先尝试 Homebrew arm64 工具链或 Rosetta 兼容模式。

  6. 严格按 Workflow 步骤执行。 一旦选定某种工作流,必须按部就班执行,不可跳过任何阶段。后一个阶段依赖前一个阶段的判定 —— 跳过质量评估或数据扩展,必然导致分析结果残缺。

输出目录

所有生成的文件(数据库、构建日志、诊断信息、数据扩展 YAML、结果)都会统一存放在同一个输出目录中。

  • 如果用户在 Prompt 中指定了输出目录,直接将其作为 OUTPUT_DIR
  • 如果未指定,默认使用 ./static_analysis_codeql_1;若该目录已存在,则自动递增为 _2_3 等。

无论哪种情况,在写入任何文件前,务必先通过 mkdir -p 创建该目录

# 解析输出目录
if [ -n "$USER_SPECIFIED_DIR" ]; then
  OUTPUT_DIR="$USER_SPECIFIED_DIR"
else
  BASE="static_analysis_codeql"
  N=1
  while [ -e "${BASE}_${N}" ]; do
    N=$((N + 1))
  done
  OUTPUT_DIR="${BASE}_${N}"
fi
mkdir -p "$OUTPUT_DIR"

输出目录会在所有工作流执行前仅解析一次。所有工作流均接收 $OUTPUT_DIR 并将产物存入其中:

$OUTPUT_DIR/
├── rulesets.txt                 # 已选定的查询包(在步骤 3 后记录)
├── codeql.db/                   # CodeQL 数据库(包含 codeql-database.yml 的目录)
├── build.log                    # 构建日志
├── codeql-config.yml            # 排除项配置(用于解释型语言)
├── diagnostics/                 # 诊断查询与 CSV 结果
├── extensions/                  # 数据扩展 YAML 文件
├── raw/                         # 未过滤的原始分析输出
│   ├── results.sarif
│   └── <mode>.qls
└── results/                     # 最终结果(仅看重点模式下为过滤后结果,全量扫描模式下为直接拷贝)
    └── results.sarif

数据库发现机制

CodeQL 数据库是以其目录内部是否存在 codeql-database.yml 标记文件来识别的。在搜索现有数据库时,务必收集所有匹配项 —— 之前运行的留存或针对不同语言建立的数据库可能会有多个。

发现命令:

# 查找所有 CodeQL 数据库(顶层目录及下一级子目录)
find . -maxdepth 3 -name "codeql-database.yml" -not -path "*/\.*" 2>/dev/null \
  | while read -r yml; do dirname "$yml"; done
  • $OUTPUT_DIR 内部: find "$OUTPUT_DIR" -maxdepth 2 -name "codeql-database.yml"
  • 全项目范围(自动检测): find . -maxdepth 3 -name "codeql-database.yml" —— 涵盖项目顶层(./db-name/)以及下一级子目录(./subdir/db-name/)中的数据库。不会向更深层搜索。

绝不要擅自假设数据库名称叫 codeql.db —— 必须通过标记文件来定位。

找到多个数据库时:

对发现的每个数据库,收集元数据以便用户选择:

# 提取每个数据库的语言和创建时间
for db in $FOUND_DBS; do
  CODEQL_LANG=$(codeql resolve database --format=json -- "$db" 2>/dev/null | jq -r '.languages[0]')
  CREATED=$(grep '^creationMetadata:' -A5 "$db/codeql-database.yml" 2>/dev/null | grep 'creationTime' | awk '{print $2}')
  echo "$db — language: $CODEQL_LANG, created: $CREATED"
done

随后调用 AskUserQuestion 供用户选择使用哪个数据库,或是重新构建一个。如果用户已经在 Prompt 中明确指定了使用哪个数据库或要求新建,请直接跳过 AskUserQuestion

快速开始

通用场景(“帮我扫描这个代码库的安全漏洞”):

# 1. 检查 CodeQL 是否已安装
if ! command -v codeql >/dev/null 2>&1; then
  echo "NOT INSTALLED: codeql binary not found on PATH"
else
  codeql --version || echo "ERROR: codeql found but --version failed (check installation)"
fi

# 2. 解析输出目录
BASE="static_analysis_codeql"; N=1
while [ -e "${BASE}_${N}" ]; do N=$((N + 1)); done
OUTPUT_DIR="${BASE}_${N}"; mkdir -p "$OUTPUT_DIR"

然后使用以下工作流完成完整流水线:构建数据库 → 创建数据扩展 → 执行分析

适用场景

  • 对代码库进行深度数据流分析,扫描安全漏洞
  • 基于源代码构建 CodeQL 数据库(支持编译型语言的构建过程)
  • 查找需要过程间污点追踪或 AST/CFG(语法树/控制流图)分析的复杂漏洞
  • 使用多个查询包完成全方位的安全审计

不适用场景

  • 编写自定义查询规则 - 建议使用专门的查询开发 Skill
  • CI/CD 集成配置 - 建议直接查阅 GitHub Actions 官方文档
  • 快速模式/匹配搜索 - 如追求速度建议使用 Semgrep 或 grep
  • 编译型语言缺少编译构建环境 - 建议改用 Semgrep
  • 单文件或轻量级分析 - 简单模式匹配使用 Semgrep 速度更快

必须拒绝的侥幸心理

以下偷懒或侥幸的借口会导致漏洞漏报,绝不可接受:

  • “跑 security-extended 就够了” - 它只是保底基线。务必检查该语言是否有 Trail of Bits 扩展包或社区包可用,它们能覆盖 security-extended 完全漏掉的漏洞类型。
  • “security-and-quality 是涵盖最广的查询集” - security-and-quality 排除掉了所有 experimental/(实验性)查询路径。对于全量扫描模式,需要同时引入 security-and-qualitysecurity-experimental。两者相差 1 到 52 条查询规则(取决于语言)。
  • “数据库构建好了,所以质量没问题” - 能构建成功并不等于提取质量高。务必进行质量评估,并将提取的文件数与预期源码文件做比对。
  • “标准框架不需要做数据扩展” - 即便是 Django/Spring 应用,也有 CodeQL 无法自动建模的自定义封装。跳过扩展意味着遗漏漏洞。
  • “编译型语言用 build-mode=none 挺好的” - 这会导致分析结果严重残缺。仅可作为走投无路时的最终手段。在 macOS 上,请先尝试 arm64 工具链变通方案或 Rosetta。
  • “在 macOS 上编译失败了,直接改用 build-mode=none 吧” - 退出码 137 是由于 arm64e/arm64 架构不匹配导致的,并不是根本上的编译失败。详见 macos-arm64e-workaround.md
  • “零漏洞说明代码很安全” - 0 个结果往往意味着数据库质量差、缺失数据模型或选错了查询包。在报告代码安全前,务必深入排查。
  • “我就跑默认查询集” / “我直接把包名传过去” - 每个包的 defaultSuiteFile 都有隐式过滤规则,可能跑出 0 个结果。务必使用显式的 .qls 查询集引用。
  • “我就把文件随便放在当前目录了” - 所有生成的文件必须存放在 $OUTPUT_DIR 中。在工作目录散落文件会导致后期无法清理,且有覆盖此前运行结果的风险。
  • “直接用找到的第一个数据库” - 现场可能存在不同语言或历次运行留下的多个数据库。只要发现多个,就应向用户展示所有选项。仅在用户明确指定时才跳过询问。
  • “用户说了‘扫描’,意思就是让我随便挑个数据库” - “扫描”不等于挑选数据库。若存在多个数据库且用户未指定,必须进行询问确认。

工作流选择

本 Skill 包含三个工作流。一旦选定某个工作流,必须按部就班完成各个阶段,严禁跳步。

工作流 目的
build-database 按顺序尝试构建方法,创建 CodeQL 数据库
create-data-extensions 针对项目 API 检测或生成数据扩展模型
run-analysis 选择规则集、执行查询并处理分析结果

自动检测逻辑

如果用户明确指定了操作(例如“构建数据库”、“对 ./my-db 执行分析”),则直接执行对应工作流。如果用户的 Prompt 已经表达了明确意图(例如“重新建个数据库”、“分析 static_analysis_codeql_2 里的 codeql 数据库”、“从零开始全面扫描”),切勿调用 AskUserQuestion 询问数据库选择。

遇到“测试”、“扫描”、“分析”等通用指令时的默认流水线: 先搜索排查现有数据库,再决策下一步。

# 通过查找 codeql-database.yml 标记文件来检索所有 CodeQL 数据库
# 搜索顶层目录及下一级子目录
FOUND_DBS=()
while IFS= read -r yml; do
  db_dir=$(dirname "$yml")
  codeql resolve database -- "$db_dir" >/dev/null 2>&1 && FOUND_DBS+=("$db_dir")
done < <(find . -maxdepth 3 -name "codeql-database.yml" -not -path "*/\.*" 2>/dev/null)

echo "Found ${#FOUND_DBS[@]} existing database(s)"
条件 采取行动
未找到数据库 解析新的 $OUTPUT_DIR,依次执行 构建 → 扩展 → 分析(全流程)
找到 1 个数据库 调用 AskUserQuestion:复用现有数据库还是重新构建?
找到多个数据库 调用 AskUserQuestion:列出所有数据库及元数据,让用户挑选或新建
用户意图明确 跳过 AskUserQuestion,直接按用户指令执行

数据库选择交互提示

当存在已有数据库且用户未明确指定使用哪一个时,通过 AskUserQuestion 展示:

header: "Existing CodeQL Databases"
question: "I found existing CodeQL database(s). What would you like to do?"
options:
  - label: "<db_path_1> (language: python, created: 2026-02-24)"
    description: "Reuse this database"
  - label: "<db_path_2> (language: cpp, created: 2026-02-23)"
    description: "Reuse this database"
  - label: "Build a new database"
    description: "Create a fresh database in a new output directory"

用户选择后的后续处理:

  • 若用户选择现有数据库:$OUTPUT_DIR 设为其父目录(或包含它的目录),将 $DB_NAME 设为选定的路径,然后依次执行 扩展 → 分析。
  • 若用户选择“构建新数据库”: 解析新的 $OUTPUT_DIR,依次执行 构建 → 扩展 → 分析。

通用说明