mcpField
C
codeql

codeql

github.com/trailofbits安全7.9k8.4k 次安装今天更新
代码仓库

关于 codeql

面向代码安全分析的 CodeQL 技能,覆盖多种语言,供需要构建数据库、配置查询并检查结果的开发者使用。它强调数据库质量、项目专属数据扩展和显式查询套件验证,以减少分析遗漏。

主要功能

  1. 01构建并评估 CodeQL 数据库
  2. 02为项目 API 创建数据扩展
  3. 03选择规则集并执行查询
  4. 04验证查询套件和数据库质量
  5. 05整理分析产物与报告

适用场景

  1. 01扫描代码库中的安全问题
  2. 02复用或创建 CodeQL 数据库
  3. 03为框架自定义 API 补充数据模型
  4. 04排查构建质量不足或零结果分析

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/trailofbits/skills --skill codeql

安装后在 Claude Code 中输入/codeql确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

agents/
openai.yaml
assets/
trail-of-bits-mark.svg
references/
build-fixes.md
diagnostic-query-templates.md
extension-yaml-format.md
important-only-suite.md
language-details.md
macos-arm64e-workaround.md
performance-tuning.md
quality-assessment.md
ruleset-catalog.md
run-all-suite.md
sarif-processing.md
threat-models.md
scripts/
build_log.sh
check_db_quality.py
find_databases.sh
generate_suite.sh
pyproject.toml
test_build_log.py
test_build_mode_claims.py
test_check_db_quality.py
test_find_databases.py
test_generation_scripts.py
test_script_flags.py
test_section_pointers.py
test_shell_blocks.py
test_suite_templates.py
test_verify_query_suite.py
verify_query_suite.py

详细介绍

CodeQL 分析

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

**技能资源:**参考文件和模板位于 {baseDir}/references/ 和 {baseDir}/workflows/。

核心原则

  1. **数据库质量不容妥协。**数据库能够构建并不代表质量合格——缓存的构建不会提取任何内容,却会报告成功。

  2. **数据扩展能捕获 CodeQL 遗漏的内容。**Django、Spring 和 Express 项目仍会通过项目专属 API 封装数据库调用、请求解析和 Shell 执行,而 CodeQL 自带的模型未涵盖这些内容。

  3. **显式引用套件可防止查询被静默丢弃。**切勿将包名称传给 codeql database analyze——每个包的 defaultSuiteFile 都会应用隐藏筛选器,可能导致零结果。请始终生成 .qls。

  4. **零项发现需要调查,而非庆祝。**这可能意味着提取质量差、缺少模型、使用了错误的包,或套件筛选所致。构建后运行 {baseDir}/scripts/check_db_quality.py,确认 {baseDir}/scripts/verify_query_suite.py 对正在使用的套件返回了零退出码——生成脚本会运行此脚本,因此仅在复用或手动编辑的套件上才需手动调用——并在报告中说明两项检查均已通过。

  5. **macOS Apple Silicon 对编译语言需要变通方案。**退出代码 137 表示 arm64e/arm64 不匹配,并非构建失败。可尝试 Homebrew arm64 工具或 Rosetta,再考虑退回 build-mode=none。

  6. **逐步遵循工作流。**每个阶段都是下一阶段的前置条件;跳过质量评估或数据扩展,会让缺口在结果中无从察觉。

每次 Bash 调用都是一个全新的 Shell

每次 Bash 调用之间都不会保留任何内容:变量、数组、从 build_log.sh 引入的函数都不例外。下面每个使用某个值的代码块,都必须在同一代码块中重新设置该值。工作流会指回此处,而不会重复说明;它们说明的是各自位置的具体影响,因为每处的故障表现都不同且不会显式报错:

  • 丢失 函数 会导致 run_logged 以 127 退出,构建梯级会将其视为失败的方法,并逐级降级至 --build-mode=none,整个过程从未调用 CodeQL
  • 丢失 数组 会使其展开为空,因此用户选择的每个 --threat-model 和 --model-packs 都会被丢弃,但最终报告仍会将它们列为已使用
  • 在 set -u 下丢失 标量 会因 unbound variable 而中止代码块

输出目录

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

  • 如果用户在提示词中指定了输出目录,请将其用作 OUTPUT_DIR。
  • 如果未指定,默认使用 ./static_analysis_codeql_1。如果该目录已存在,则依次递增为 _2、_3 等。

无论哪种情况,都必须在写入任何文件之前使用 mkdir -p 创建目录。

运行此操作前,将 USER_SPECIFIED_DIR 设为用户提示词中的字面路径;若要自动递增,则保持未设置。除此之外,不要在任何地方为它赋值。

# Resolve output directory
USER_SPECIFIED_DIR="${USER_SPECIFIED_DIR:-}"   # substitute the user's path here, if any
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                 # Selected query packs (logged after Step 3)
├── codeql.db/                   # CodeQL database (dir containing codeql-database.yml)
├── build.log                    # Build log
├── codeql-config.yml            # Exclusion config (interpreted languages)
├── diagnostics/                 # Diagnostic queries and CSVs
├── extensions/                  # Data extension YAMLs
├── raw/                         # Unfiltered analysis output
│   ├── results.sarif
│   └── run-all.qls | important-only.qls
└── results/                     # Final results (filtered for important-only, copied for run-all)
    └── results.sarif
数据库发现

CodeQL 数据库通过其目录中是否存在 codeql-database.yml 标记文件来识别。搜索现有数据库时,始终收集所有匹配项——之前的运行可能留下多个数据库,也可能有适用于不同语言的数据库。

发现命令。 find_databases.sh 每行输出一个数据库路径,并过滤掉失败构建遗留的标记文件。在同一个代码块中构建数组并从中选择——每次 Bash 调用都是一个全新的 shell,因此在此处构建的数组到下一次调用时会变成空数组,最终运行会得出不存在数据库的结论:

# Command substitution, not `done < <(...)`: a process substitution discards the script's
# exit status, so "codeql is not on this shell's PATH" (exit 2) would arrive as an empty
# list and route to "build a new database" with three good ones sitting on disk.
if ! DB_LIST=$("{baseDir}/scripts/find_databases.sh" "${OUTPUT_DIR:-.}" .); then
  echo "ERROR: database discovery failed — see the message above" >&2
  exit 1
fi

FOUND_DBS=()
while IFS= read -r db; do
  [ -n "$db" ] || continue
  FOUND_DBS+=("$db")
done <<<"$DB_LIST"

echo "Found ${#FOUND_DBS[@]} existing database(s)"

# The metadata the selection prompt needs, collected here rather than in a block of its
# own: FOUND_DBS is gone by the next Bash call, and a loop over an array that no longer
# exists prints nothing and reports success.
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

切勿假设数据库名为 codeql.db——应通过其标记文件来发现数据库。

**找到多个数据库时:**使用 AskUserQuestion,让用户根据上方打印的语言和创建时间,选择要使用的数据库或构建新数据库。AskUserQuestion 最多接受四个选项,因此如果数据库数量超过四个,应提供最近的三个数据库和“构建新数据库”,并在提示文本中列出其余数据库。如果用户在提示中明确说明要使用哪个数据库或要构建新数据库,则跳过 AskUserQuestion。

快速开始

对于常见情况(“扫描此代码库以查找漏洞”):

# Verify CodeQL is installed. Stop here if it is not — every later command fails with
# a less informative error, and the run wastes a build cycle before saying why.
if ! command -v codeql >/dev/null 2>&1; then
  echo "ERROR: codeql not found on PATH. Install it with one of:" >&2
  echo "  gh extension install github/gh-codeql   # then: gh codeql install-stub" >&2
  echo "  brew install --cask codeql" >&2
  echo "  https://github.com/github/codeql-action/releases  (codeql-bundle)" >&2
  exit 1
fi

# jq parses `codeql resolve database --format=json` in the very next step. Without it
# CODEQL_LANG comes back empty and the run continues against the wrong language.
if ! command -v jq >/dev/null 2>&1; then
  echo "ERROR: jq not found on PATH (brew install jq / apt install jq)" >&2
  exit 1
fi

# uv runs both guard scripts and both suite generators. Check it here rather than at
# suite generation, which is after the build — otherwise a machine without uv spends
# the whole build before failing.
if ! command -v uv >/dev/null 2>&1; then
  echo "ERROR: uv not found on PATH (https://docs.astral.sh/uv/getting-started/)" >&2
  exit 1
fi

codeql --version

然后使用上文输出目录中的代码块解析 OUTPUT_DIR——它会遵循用户指定的目录,而直接自动递增则不会。

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

应避免的错误理由

这些捷径会导致漏报。不要接受:

  • “security-extended 就够了” - 这是基准方案。始终检查该语言是否有 Trail of Bits 包和 Community Packs。它们能发现 security-extended 完全遗漏的类别。
  • “security-and-quality 是范围最广的套件” - security-and-quality 会排除所有 experimental/ 查询路径。对于运行全部模式,同时导入 security-and-quality 和 security-experimental。根据语言不同,两者之间相差 1–52 个查询。
  • “数据库构建成功,所以没问题” - 数据库构建成功并不意味着提取效果良好。始终进行质量评估,并核对文件数量与预期源文件数量。
  • “标准框架不需要数据扩展” - 即使是 Django/Spring 应用也有 CodeQL 未建模的自定义包装器。跳过扩展意味着漏掉漏洞。
  • “对于编译型语言,build-mode=none 没问题” - 这会导致分析严重不完整。仅在绝对无计可施时使用。在 macOS 上,先尝试 arm64 工具链变通方案或 Rosetta。
  • “在 macOS 上构建失败,那就用 build-mode=none” - 退出代码 137 是由 arm64e/arm64 不匹配导致的,并非根本性的构建失败。请参阅 macos-arm64e-workaround.md。
  • “没有发现结果就说明代码安全” - 运行 check_db_quality.py 和 verify_query_suite.py,并报告检查通过。没有这些检查,零发现与未提取任何内容的数据库会产生相同的输出。
  • “我就运行默认套件” / “我直接传入包名就行” - 每个包的 defaultSuiteFile 都会应用隐藏过滤条件,可能导致结果为零。始终使用明确的套件引用。
  • “我把文件放在当前目录就行” - 所有生成的文件都必须放在 $OUTPUT_DIR 中。将文件散落在工作目录中会导致无法清理,还可能覆盖之前的运行结果。
  • “直接用我找到的第一个数据库就行” - 不同语言或之前的运行可能会产生多个数据库。找到多个数据库时,向用户展示所有选项。只有在用户已指定要使用哪个数据库时,才跳过提示。
  • “用户说了‘扫描’,这就表示他们希望我选择数据库” - “扫描”并不等于选择数据库。如果存在多个数据库,而用户没有指定其中一个,就应询问。

工作流选择

此技能有三个工作流。选择工作流后,请按步骤执行,不要跳过任何阶段。

这些运行耗时较长。数据库构建有四种备用方法,因此请使用任务工具跟踪进度。根据运行情况,决定哪些步骤值得跟踪。

工作流用途
build-database依次使用构建方法创建 CodeQL 数据库
create-data-extensions检测或生成项目 API 的数据扩展模型
run-analysis选择规则集、执行查询并处理结果
无人值守构建

此插件附带 /static-analysis:codeql-build,可端到端执行 build-database 的步骤:检测语言和工具链,按顺序尝试各方法,并在每个阶段之间应用 build-fixes.md 中的修复,然后执行质量门禁。

/static-analysis:codeql-build {"target": "/abs/path", "lang": "cpp"}

此过程不会提问。如果所有方法都失败,或者数据库虽已构建但低于质量阈值,就会返回状态 — no-method-succeeded 和 built-below-threshold — 供你在此处处理,因为剩余的提取器错误是否仅出现在无需分析的代码中,需要人为判断,运行本身无法决定。

如果构建过程漫长且不确定,而你希望自动推进直到得出结论,请使用此方式。如果你想决定尝试哪种方法,或者需要在构建失败时即时分析原因,请手动执行 build-database.md。

自动检测逻辑

如果用户明确指定要执行的操作(例如,“构建数据库”、“对 ./my-db 运行分析”),则直接执行相应工作流。如果用户的提示已清楚表明其意图,请勿调用 AskUserQuestion 来选择数据库 — 例如,“构建一个新数据库”、“分析 static_analysis_codeql_2 中的 codeql 数据库”、“从头开始运行完整扫描”。

对于“测试”、“扫描”、“分析”或类似请求的默认流程: 使用上文数据库发现中的命令查找现有数据库,然后再决定。

条件操作
未找到数据库确定新的 $OUTPUT_DIR,依次执行构建 → 扩展 → 分析(完整流程)
找到一个数据库使用 AskUserQuestion:复用该数据库还是新建?
找到多个数据库使用 AskUserQuestion,最多提供四个选项 — 参见数据库发现
用户已明确说明意图跳过 AskUserQuestion,直接按用户指示操作
数据库选择提示

如果找到现有数据库,且用户未明确指定要使用哪个数据库,请通过 AskUserQuestion 展示这些数据库,标题为“现有 CodeQL 数据库”。每个选项都要包含上文收集到的路径、语言和创建时间 — ./static_analysis_codeql_1/codeql.db (language: python, created: 2026-02-24) — 最后一个选项设为“构建新数据库”。

选择后:

  • 如果用户选择现有数据库: 将 $OUTPUT_DIR 设为其父目录(或包含该数据库的目录),将 $DB_NAME 设为所选路径,然后继续执行扩展 → 分析。
  • 如果用户选择“构建新数据库”: 确定新的 $OUTPUT_DIR,依次执行构建 → 扩展 → 分析。
通用决策提示

如果提示中未明确数据库或工作流,请通过 AskUserQuestion 提供四种工作流 — 完整扫描(推荐)、构建数据库、创建数据扩展、运行分析 — 并列出找到的数据库和确定的 $OUTPUT_DIR。


参考索引

文件内容
脚本
scripts/verify_query_suite.py当解析出的查询数为零时使套件失败。生成脚本会运行它;仅在重用或手动编辑套件时手动调用
scripts/check_db_quality.py当数据库没有可分析的源代码时使其失败。每次构建后运行
scripts/build_log.shlog_step/run_logged 辅助函数;在任何构建步骤前先加载
scripts/find_databases.sh每行输出一个 codeql resolve database 可接受的数据库。在读取它的代码块中据此构建数组
scripts/generate_suite.sh写入 run-all 或 important-only .qls,并验证其解析出的查询数非零
参考资料 — 三种工作流列于工作流选择
references/macos-arm64e-workaround.mdApple Silicon 构建跟踪的解决方法
references/build-fixes.md构建失败修复目录
references/quality-assessment.md数据库质量指标与改进
references/extension-yaml-format.md数据扩展 YAML 列定义和示例
references/sarif-processing.md处理 SARIF 输出的 jq 命令
references/diagnostic-query-templates.md用于枚举源/汇的 QL 查询
references/important-only-suite.md仅重要项套件模板与生成
references/run-all-suite.md全部运行套件模板
references/ruleset-catalog.md按语言列出的可用查询包
references/threat-models.md威胁模型配置
references/language-details.md特定语言的构建和提取详情
references/performance-tuning.md内存、线程和超时配置

成功标准

完整的 CodeQL 分析运行应满足以下条件:

  • 已解析输出目录(由用户指定或使用自动递增的默认值)
  • 所有生成的文件均存储在 $OUTPUT_DIR 中
  • 已构建数据库(通过 codeql-database.yml 标记发现),且 {baseDir}/scripts/check_db_quality.py 的退出码为零
  • 已评估数据扩展 — 要么创建在 $OUTPUT_DIR/extensions/ 中,要么明确说明跳过的理由
  • 使用明确的套件引用(而非默认包套件)运行分析,且 {baseDir}/scripts/verify_query_suite.py 对该套件的退出码为零
  • 已使用或明确排除所有已安装的查询包(官方 + Trail of Bits + Community)
  • 已将选定的查询包记录到 $OUTPUT_DIR/rulesets.txt
  • 未经过滤的结果已保存在 $OUTPUT_DIR/raw/results.sarif
  • 最终结果位于 $OUTPUT_DIR/results/results.sarif 中(仅重要项模式下经过过滤;全部运行模式下直接复制)
  • 已调查零发现结果(数据库质量、模型覆盖范围、套件选择)
  • 构建日志已保存在 $OUTPUT_DIR/build.log,其中包含所有命令、修复和质量评估

评论

支持 Markdown