技能使用指南

codeql(CodeQL静态分析Skill)Skill 是什么?如何下载安装使用?

CodeQL静态分析Skill把代码库编译成可查询数据库,支持跨过程控制流与数据流追踪,可自定义QL查询并接入CI门禁。本文详解技能安装步骤、建库与分析命令、查询编写与测试方法、与Semgrep等方案对比及典型应用场景,附常见问题答疑,帮安全研究员与研发团队快速上手深度静态分析,立即收藏实践。

CodeQL静态分析Skillcodeql
10 个章节 约 21 分钟阅读 AI 智能生成

CodeQL静态分析Skill:把整个代码库变成可查询的数据库,让跨过程漏洞无处可藏

  • 定位清晰:CodeQL 不是传统"规则匹配"式扫描器,而是一个把源代码编译成可查询数据库的静态分析框架,代码即数据,漏洞即查询。
  • 核心能力:原生支持跨过程与过程内的控制流、数据流分析,可对抽象语法树、控制流图、数据流图做细粒度操控。
  • 上手路径:三步走——建库(codeql database create)→ 分析(codeql database analyze)→ 审查(SARIF 结果),本技能把这条链路整理成可直接照抄的命令与查询模板。
  • 门槛提示:支持 C/C++、C#、Go、Java、Kotlin、JavaScript/TypeScript、Python、Ruby、Swift;编译型语言必须能真实构建;闭源代码库需 GitHub Enterprise 或 Advanced Security 许可。
  • 适合谁:需要深度数据流追踪的安全研究员、做代码审计的 AppSec 团队、希望把已知漏洞模式固化成 CI 门禁的工程团队。

该技能叫什么?如何下载安装 AI 技能提升开发效率?

技能中文名:CodeQL静态分析Skill 技能英文名:codeql 技能ID:13548 技能类型:工具

它要解决的问题很具体:当你想知道"用户输入到底有没有流到这个危险函数"“这个返回值有没有人检查”"某个指针会不会被释放后又使用"这类跨文件、跨函数、跨调用链的问题时,正则搜索和单文件模式匹配会大量漏报和误报。CodeQL 用"把代码库编译成关系数据库、再用声明式查询语言 QL 提问"的方式解决这个问题,而本技能就是把 CodeQL 的建库、分析、写查询、跑测试、接 CI 这一整套流程,整理成可以按步骤执行的知识包与命令模板。

安装前提

  1. 一个可用的 AI 技能客户端/平台,且已支持加载"工具"类技能(具体入口与界面以官方说明为准)。
  2. 本地具备 CodeQL CLI 运行环境:macOS 或 Linux(Homebrew 安装路径),或按官方发布页手动下载对应架构的压缩包。
  3. 若是编译型语言(C/C++、Swift),需要项目本身可构建,并准备好构建命令(如 make -j8)。

安装步骤

第一步:在技能平台侧启用该技能。 通过技能 ID 13548 或其英文名 codeql 检索并启用,具体安装入口、是否需要登录授权,以官方说明为准。启用后,你在对话里提出的"帮我分析这段 C 代码的数据流"之类的需求,会按 CodeQL 的标准工作流被拆解成建库、分析、查询、结果解读几个环节。

第二步:在本地安装 CodeQL CLI。 官方给出两条路径:

  • Homebrew(macOS/Linux):
brew install --cask codeql

第三步:保持更新。 CodeQL 迭代很快,Homebrew 用户执行 brew upgrade codeql,手动安装用户重新下载新版捆绑包覆盖即可。

第四步:验证是否生效。

codeql --version

能正常打印版本号,说明 CLI 已就绪。接着可以试着列出已安装的查询包,确认查询库完整:

codeql resolve qlpacks

如果你还希望有图形化的查询编辑与 AST 可视化体验,可另行安装编辑器扩展:VSCode 的 CodeQL 扩展(提供 LSP 支持、语法高亮、查询运行、AST 可视化),或 Neovim 的 codeql.nvim。

该技能的主要功能和特点

  • 跨过程数据流追踪:这是与普通扫描器拉开差距的地方。它能追踪一个变量从函数 A 的参数进入、穿过若干层调用、最终流入函数 B 的危险参数的全过程,而不是只在单个文件里"看见什么报什么"。
  • 控制流图与抽象语法树级操作:可以精确表达"这个调用是否被 if 或 switch 包裹""这个基本块是否可达"等条件,适合描述复杂的误报过滤逻辑。
  • 声明式查询语言 QL:语法接近 Java,查询表达式接近 SQL,典型查询体只有 from ... where ... select ... 三段式,可读性高,便于团队共享和评审。
  • 自定义类与谓词复用:可以把"所有 memcpy 调用"抽象成一个 MemcpyCall 类,并派生 getDestination()、getSource()、getSize() 等方法,后续查询直接复用。
  • 递归与传递闭包:用 *(零次或多次)和 +(一次或多次)表达可达性、调用链深度等递归关系,避免手写递归谓词。
  • 标准查询包即插即用:codeql/cpp-queries 等官方包覆盖大量常见缺陷与安全模式;也可以下载第三方包,例如 codeql pack download trailofbits/cpp-queries trailofbits/go-queries。
  • 查询工程化与测试体系:codeql pack init 初始化查询包、codeql pack add codeql/cpp-all 引入标准库依赖、codeql test run 跑回归测试,并支持 .expected 基线与 .qlref 引用,做到"查询也是代码,也要测试"。
  • SARIF 输出对接生态:分析结果可输出为 SARIF 或 CSV,导入 IDE(如 VSCode SARIF Explorer 扩展)、代码扫描面板或自定义 CI/CD 管道。
  • 与 GitHub Actions 深度集成:官方提供 init / autobuild / analyze 三个 Action,可把 security-extended、security-and-quality 查询集与自定义查询包同时挂到 PR 和定时任务上。

与普通工具相比强在哪?一句话:同样一个问题,普通工具回答"有没有出现这个字符串",CodeQL 回答"这个不可信输入有没有可能沿着这条调用链到达这个危险点"。

如何使用该技能?

以下步骤对应 CodeQL 的官方核心工作流,也是本技能引导你完成的主线。

步骤 1:确认适用性与语言。 先确定要分析的语言,并确认项目可构建。编译型语言必须先能真实构建,否则数据库信息不完整。

步骤 2:清理构建产物。 建库前确保代码库处于干净状态,例如执行 make clean、go clean 等等效命令。

步骤 3:创建 CodeQL 数据库。

# C/C++
codeql database create codeql.db --language=cpp --command='make -j8'

# 使用 CMake 等外部构建时,补充源码根目录
codeql database create codeql.db --language=cpp --source-root=/path/to/source --command='cmake --build build'

# 解释型语言
codeql database create codeql.db --language=python
codeql database create codeql.db --language=javascript

# 支持自动检测构建的语言
codeql database create codeql.db --language=go
codeql database create codeql.db --language=java

步骤 4:运行分析。 用预编译查询包扫描数据库,输出 SARIF 或 CSV:

codeql database analyze codeql.db --format=sarif-latest --output=results.sarif -- codeql/cpp-queries

步骤 5:审查结果。 SARIF 文件里每条发现都带位置、严重性和描述。可以导入 VSCode(配合 SARIF Explorer 扩展)逐条查看,或直接接入 CI 流水线做门禁。

步骤 6:编写自定义查询。 基础结构如下,它选出所有把 memcpy 目标参数出现位置:

import cpp

from FunctionCall call
where call.getTarget().getName() = "memcpy"
select call.getLocation(), call.getArgument(0)

把重复模式封装成类,写法更清晰:

import cpp

class MemcpyCall extends FunctionCall {
  MemcpyCall() { this.getTarget().getName() = "memcpy" }
  Expr getDestination() { result = this.getArgument(0) }
  Expr getSource() { result = this.getArgument(1) }
  Expr getSize() { result = this.getArgument(2) }
}

from MemcpyCall call
select call.getLocation(), call.getDestination()

输入与输出说明:输入是数据库 + .ql 查询文件;输出取决于查询声明的 @kind。problem 类型输出必须是 (Location, string),path-problem 类型输出必须是 (DataFlow::Node, DataFlow::PathNode, DataFlow::PathNode, string)——后者用来画出完整的污点传播路径。

步骤 7:补全查询元数据。 元数据写在文件头部注释里,@name、@id、@description、@kind、@problem.severity、@precision 是必填项,否则 SARIF 输出会缺少严重度和描述。例如:

/**
 * @name 未处理的错误返回值
 * @id custom/unhandled-error
 * @description 返回错误代码但未检查的函数调用
 * @kind problem
 * @problem.severity warning
 * @precision medium
 */

步骤 8:测试查询。 建立测试包(qlpack.yml 中声明 extractor: cpp 与依赖),测试目录内放 test.c、MemcpyCall.qlref、MemcpyCall.expected,然后运行:

codeql test run -- path/to/test/pack/

若 .expected 缺失或不正确,会生成 .actual,人工核对无误后重命名为 .expected 即可固定基线。

步骤 9:接入 CI。 在 GitHub Actions 中启用代码扫描,或使用高级设置工作流:github/codeql-action/init@v3 指定语言,autobuild@v3 自动构建(编译型语言可替换为 make -j8 等自定义命令),analyze@v3 产出结果。想同时跑自定义查询,在 init 步骤加参数:

- uses: github/codeql-action/init@v3
  with:
    queries: security-extended,security-and-quality
    packs: trailofbits/cpp-queries

仓库本地查询用相对路径(注意前缀 .),且必须属于某个含 qlpack.yml 的查询包。

同类型竞品对比分析

方案名称 定位 核心功能 安装/使用门槛 适用场景 优势与不足
CodeQL(本技能) 代码即数据库的静态分析框架 跨过程控制流与数据流分析、AST/CFG/DFG 细粒度控制、自定义 QL 查询与查询包测试 需安装 CLI(brew install --cask codeql 或手动下载);编译型语言必须可构建;自定义查询学习曲线陡峭、标准库文档偏少 复杂污点追踪、深层漏洞挖掘、把已知缺陷固化为 CI 门禁 优势:跨过程推理能力强、可复用可测试、SARIF 生态完善。不足:分析耗时较长、单库单语言、闭源代码库需商业许可
Semgrep 轻量级模式匹配式扫描器 基于语法模式的规则匹配、规则编写简单、扫描速度快 门槛低,规则接近源码片段即可表达,无需构建项目 快速上手、PR 级轻量检查、无构建环境的仓库 优势:上手快、反馈快、适合前置过滤。不足:跨过程数据流能力有限,复杂漏洞类别容易漏报
SonarQube 类平台 面向团队的代码质量与安全平台 规则集扫描、质量门禁、技术债与重复率度量、报告看板 需部署服务端与扫描器,配置较重 团队级代码质量治理、长期指标追踪 优势:看板与流程管理成熟。不足:深度定制分析逻辑的自由度不如查询式框架,复杂数据流场景需额外能力
普通文本搜索(grep/正则) 最原始的代码检索 字符串与正则匹配 几乎零门槛 明确关键字的快速定位、初步摸排 优势:即时、无需环境。不足:无法理解语义与调用关系,误报漏报都高,不能替代静态分析

怎么选? 实践中常见的组合是:先用 Semgrep 做快速模式检查拿到即时反馈,再用 CodeQL 做深层跨过程分析补齐漏网之鱼;本技能文档也明确把 semgrep 与 sarif-parsing 列为"相关技能",前者用于前置快筛,后者用于在自定义 CI/CD 管道中处理 CodeQL 的 SARIF 输出。

该技能的典型应用场景与实际体验情况

场景一:安全研究员在 C/C++ 项目里追踪不可信输入 痛点:想确认某个网络读入的缓冲区,是否会经由多层函数调用最终进入 memcpy 的源参数。使用方式:先建 cpp 数据库,再基于标准库写一条 path-problem 查询,把源、汇、传播路径声明清楚,输出带完整路径的告警。 实际体验:一旦查询写对,效果非常直观——它给出的不只是一个位置,而是一条可逐步复核的传播链路,人工复核成本大幅下降。注意事项:建库前必须先 make clean 再让 CodeQL 接管构建,否则数据库信息不全,链路会断在莫名其妙的地方。

场景二:后端团队把漏洞模式固化进 CI 门禁 痛点:某个"函数返回错误码但调用方没检查"的问题修了又犯,CodeQL 文档里正好有对应示例查询(通过函数名匹配 error/Error,并排除被 if 或 switch 包裹的调用)。使用方式:把查询放进仓库内的查询包,在 GitHub Actions 的 init 步骤用相对路径挂上,配合 PR 触发。 实际体验:一次配置长期生效,新代码合入前就能拦住。注意事项:务必补全 @problem.severity 与 @precision 元数据,否则结果在面板里没有严重度分级,很难定门禁阈值。

场景三:代码审计团队分析含第三方依赖的完整工程 痛点:只扫自研代码会漏掉"数据流穿过第三方库再回到自研代码"的路径。使用方式:建库时把第三方库包含进来,再把告警按文件位置过滤。 实际体验:覆盖率明显提升。注意事项:官方明确推荐"包含第三方库、按位置过滤问题",而不是在建库阶段排除文件——因为排除后 CodeQL 对这些文件只有部分认知,无法推理穿过它们的数据流。

场景四:团队沉淀自己的查询库 痛点:每个项目的审计经验散落在个人笔记里。使用方式:codeql pack init <scope>/<name> 初始化查询包,codeql pack add codeql/cpp-all 引入标准库,搭建 codeql-workspace.yml 工作空间文件,再用 codeql test run 建立回归测试。 实际体验:从"人肉经验"变成"可测试资产"的感觉很强,配合 CI 中的查询测试工作流(并缓存 ~/.codeql 加速),迭代速度可观。注意事项:容易踩的坑包括——忘记创建 codeql-workspace.yml 导致 CLI 找不到查询包、在查询包里用相对导入导致解析失败。

总体体验:上手难度是中等偏高,难点不在命令(就那么几条),而在 QL 语言与标准库的熟悉度;效果上限很高,尤其适合"单文件模式匹配明显不够用"的复杂漏洞类别;需要注意的坑集中在构建干净度、元数据完整性、单库单语言限制以及复杂查询的运行耗时。

该技能能为用户带来的价值

  • 把"看不出来"变成"看得见":跨过程数据流与控制流分析,让藏在多层调用背后的风险暴露出来,这是单文件匹配完全做不到的能力层。
  • 把"人肉经验"变成"可测试资产":自定义查询是代码,可以进版本库、可以写 .expected 基线回归测试、可以被同事复用,团队安全能力不再是"某个大佬记得"。
  • 把安全检查前移到提交前:通过 GitHub Actions 集成,扫描从"上线前集中排查"变成"每次 PR 自动跑",修复成本按阶段显著下降——越早发现,改动面越小。
  • 降低深度分析的使用门槛:本技能把建库、分析、写查询、测试、接 CI 的完整链路整理成可直接照抄的命令与模板,省去大量翻文档与试错时间,尤其缓解了官方"标准库文档匮乏"的痛点。
  • 长期价值在复用:一个查询包一旦成型,可以在所有同语言项目上反复运行,边际成本接近于零,越用越值钱。

常见问题 FAQ

Q1:这个技能怎么安装?需要付费吗? 分两层:技能层通过技能 ID 13548 或英文名 codeql 在技能平台启用(具体入口与是否收费以官方说明为准);工具层需要在本地安装 CodeQL CLI,macOS/Linux 可执行 brew install --cask codeql,或从官方发布页面手动下载对应架构的捆绑包,装完用 codeql --version 验证。需要注意 CodeQL 本身对闭源代码库有许可要求——需要 GitHub Enterprise 或 Advanced Security 许可,具体授权方式与价格以官方说明为准。

Q2:它和 Semgrep 这类轻量扫描器怎么选? 不是二选一,而是分层用。单文件模式匹配就够用的场景,Semgrep 更快、规则更好写;当你需要跨过程的控制流与数据流查询、需要对 AST/CFG/DFG 做细粒度控制、或漏洞类别本身超出单文件匹配能力时,才值得上 CodeQL。另外,如果没有源码访问权限、无法构建项目,或者分析时间极其敏感,官方也建议考虑替代方案。

Q3:为什么我的分析结果漏了很多,或者数据流断在半路? 先检查三个高频原因:一是建库前没清理构建产物(应执行 make clean 或等效命令,再让 CodeQL 接管构建);二是在建库时排除了第三方库,导致无法推理穿过这些文件的数据流(应包含库、按位置过滤告警);三是编译型语言项目本身没构建成功,数据库信息不完整。另外记住每个数据库只对应一种语言,多语言项目需要建多个数据库。

Q4:自定义查询一定需要写代码吗?有没有低门槛路径? 可以先不写。官方预编译查询包(如 codeql/cpp-queries)覆盖大量常见问题,用 codeql database analyze 直接跑即可;也能用 codeql pack download trailofbits/cpp-queries 这类命令引入第三方查询包。只有当你要找的问题属于团队特有模式时,才需要写 QL。写的时候建议从"复用一个查询 + 加一个 where 条件"开始,而不是一上手就写复杂的数据流查询。

Q5:适合谁用?团队落地要注意什么? 适合需要深度数据流追踪的安全研究员、做代码审计的 AppSec 团队,以及希望把已知缺陷固化成 CI 门禁的工程团队。落地时注意几点:把查询包和工作空间文件一起入库(缺 codeql-workspace.yml 会导致 CLI 找不到包);每条查询都补齐必填元数据,否则结果缺少严重度与描述;用 codeql test run 建立回归基线;对大型代码库预留足够的扫描时间,复杂跨过程查询确实可能跑很久。