为 CodeQL 准备数据库
CodeQL 将代码视为数据。 CodeQL 分析依赖于从代码中提取关系数据,并使用它生成 CodeQL 数据库。 这些数据库包含有关代码库的所有重要信息。
然后,可以针对此数据库运行 CodeQL 查询,以识别安全漏洞、bug 和其他错误。 可以编写自己的查询或运行 GitHub 研究人员和社区参与者编写的标准 CodeQL 查询。
可以使用独立的 CodeQL CLI 创建和分析 CodeQL 数据库。 分析数据库会在静态分析结果交换格式(SARIF)中生成结果,该格式可以上传到GitHub存储库以查看警报详细信息。
CodeQL 扫描体系结构
CodeQL 扫描遵循将源代码转换为可查询数据的管道,执行安全查询,并将结果发布为代码扫描警报。
扫描工作流为:
- 源代码: CodeQL 从正在分析的提交中的仓库内容开始。
- 提取: 特定于语言的提取程序读取代码并收集有关源文件、语法、控制流和数据流的事实。
- 数据库创建: 提取的事实存储在 CodeQL 数据库中。 每个数据库表示代码库中的一种语言。
- 查询执行:CodeQL 针对数据库运行GitHub维护的查询、社区查询或自定义查询。
- SARIF 生成: 查询结果以 静态分析结果交换格式(SARIF)编写。
- GitHub代码扫描:SARIF 结果将上传到GitHub并显示为代码扫描警报。
此体系结构将代码提取与查询执行分开。 创建数据库后,可以针对同一数据库运行不同的查询套件,而无需再次提取代码。
语言策略
CodeQL 支持已编译和解释的语言,但提取策略取决于语言类型。
已编译的语言
对于编译型语言,例如:
- C/C++
- C#
- Java
- Kotlin
- Rust
- Swift
- Go
CodeQL 通常需要了解项目是如何构建的。 在创建数据库期间,CodeQL 可能会监视生成过程,以便它可以提取编译器处理的源文件。
对于最可靠的结果,请配置显式生成命令,而不是依赖于 自动生成 或 无生成 选项。
解释型语言
对于解释型语言,例如:
- Python
- JavaScript/TypeScript
- Ruby
CodeQL 直接从源代码中提取信息,而无需单独的生成命令。
多语言存储库
对于包含多个支持语言的存储库:
- 为每个语言创建单独的数据库。
- 在GitHub Actions中,使用语言矩阵,以便正确初始化、提取和分析每种语言。
为 CodeQL 准备数据库
生成 CodeQL 数据库之前:
- 安装和配置 CodeQL CLI。
- 查看要分析的代码库版本。
对于编译型语言:
- 确保项目已准备好进行构建。
- 事先安装所有必需的依赖项。
- CodeQL 提取每个源文件的关系表示形式,以创建数据库。
对于解释型语言:
- 提取程序直接在源代码上运行。
- 依赖关系会在提取过程中自动解析。
对于编译的语言,CodeQL 监视正常的生成过程。 每次编译器处理源文件时,CodeQL 都会创建一个副本并提取分析所需的所有相关信息。
CLI 设置
按照以下步骤安装 CodeQL CLI。
1.下载 CodeQL CLI 捆绑包
建议的安装方法是下载捆绑包,这可确保 CLI、库和查询包之间的兼容性。
捆绑包包括:
- CodeQL 命令行界面
- 兼容的 CodeQL 查询和库
- 预编译查询包
下载捆绑包:
- 转到 CodeQL 公共存储库的 “发布 ”页。
- 在 “资产”下下载特定于平台的捆绑包。
发布页面还包括:
- 发行说明
- 以前的版本
-
codeql-bundle.tar.gz,它支持所有平台
2.提取存档
将 .zip 存档解压缩到所选的目录中。
macOS Catalina(或更高版本)的用户必须完成其他设置步骤,如 CodeQL CLI 文档中所述。
3. 运行 CodeQL
提取后,可执行以下任一操作:
- 运行:
<extraction-root>/codeql/codeql
或
- 添加:
<extraction-root>/codeql
添加到您的系统 PATH 中,这样您就可以直接调用 CLI:
codeql
现在可以运行 CodeQL 命令。
验证 CLI 设置
运行以下命令,验证安装是否正常工作。
显示已安装的 CodeQL 包:
codeql resolve packs
如果可执行文件不在你的 PATH中,请使用:
<extraction-root>/codeql/codeql resolve packs
如果缺少预期的语言包,请验证是否已下载 CodeQL 捆绑包,而不是独立 CLI。
显示支持的语言:
codeql resolve languages
数据库创建
从项目的根目录创建 CodeQL 数据库:
codeql database create <database> --language=<language-identifier>
替换为:
- 将
<database>替换为目标目录。 - 带有要分析的语言标识符的
<language-identifier>。
还可以使用以下选项:
| 选项 | Purpose |
|---|---|
--source-root |
指定包含源代码的根目录。 |
--db-cluster |
创建多种语言的数据库。 |
--command |
指定已编译语言的生成命令。 对于 Python、Ruby 或 JavaScript,则不是必需的。 |
--no-run-unnecessary-builds |
与 --db-cluster 一起使用时,可跳过不必要的构建。 |
成功执行后:
- 将创建新的数据库目录。
- 使用
--db-cluster时,会为每个语言创建一个子目录。
每个数据库都包含:
- 关系分析数据
- 源存档
- CodeQL 分析所需的元数据
源存档是创建数据库时源文件的快照,在显示分析结果时使用。
数据库生成和性能注意事项
创建 CodeQL 数据库后,请务必了解数据库生成的工作原理以及它如何影响性能。
数据库生成方法
可以使用以下任一方法生成 CodeQL 数据库:
CodeQL命令行界面 (CLI)
创建数据库并手动运行分析。
此方法适用于:
- 地方发展
- Debugging
- 高级配置
GitHub Actions工作流
大多数组织通过GitHub Actions自动生成数据库。
典型的工作流:
- 初始化 CodeQL。
- 创建数据库。
- 运行查询。
- 将 SARIF 结果上传到GitHub。
按语言划分的数据库
CodeQL 为每个受支持的语言创建单独的数据库。
每种语言:
- 使用其自有提取器。
- 使用自己的数据库架构。
- 被独立分析。
对于多语言存储库,任一:
- 将
--db-cluster选项与 CLI 配合使用。 - 在 GitHub Actions 中配置语言矩阵。
语言矩阵支持并行分析和完整的语言覆盖。
针对编译型语言的基于构建的提取
对于编译型语言:
- CodeQL 监视生成过程。
- 构建必须成功完成。
- 自动 构建 并不能在每个项目中都可靠地工作。
为了获得最佳结果,请在分析之前定义显式生成步骤。
对于解释语言,CodeQL 直接从源代码中提取,而无需生成。
性能注意事项
数据库创建和分析时间取决于多种因素。
存储库大小
较大的存储库需要更多的提取和分析时间。
多语言
使用语言矩阵并行分析语言并减少总运行时。
CI 资源
CodeQL 分析可能占用大量资源。
为运行器增加 CPU 或内存可显著提升性能。
分析范围
可以通过限制扫描的代码来缩短分析时间,例如,通过排除:
- 测试文件
- 生成的代码
一般情况下,分析时间与正在处理的源代码量成正比。
数据库创建和重新生成
CodeQL 数据库表示特定时间点代码库的快照。
- 为每个分析运行创建一个新数据库。
- 数据库不会增量更新。
- 对代码库的任何更改都需要新的数据库。
通常在以下情况下重新生成数据库:
- 推送新提交。
- 打开或更新拉取请求。
- 生成配置更改。
- 查询集或分析配置的更改。
由于数据库生成是每次扫描的一部分,因此最好将扫描与有意义的事件对应起来,例如拉取请求或计划运行。
提取装置
提取程序是为每个输入文件生成关系数据和源引用的工具,可以从中构建 CodeQL 数据库。 CodeQL 支持的每种语言都有一个提取程序。 此结构可确保提取过程尽可能准确。
每个提取程序都定义了自己的一组配置选项。 输入 codeql resolve extractor --format=betterjson 会导致数据格式化为如下示例:
{
"extractor_root": "/home/user/codeql/java",
"extractor_options": {
"option1": {
"title": "Java extractor option 1",
"description": "An example string option for the Java extractor.",
"type": "string",
"pattern": "[a-z]+"
},
"group1": {
"title": "Java extractor group 1",
"description": "An example option group for the Java extractor.",
"type": "object",
"properties": {
"option2": {
"title": "Java extractor option 2",
"description": "An example array option for the Java extractor",
"type": "array",
"pattern": "[1-9][0-9]*"
}
}
}
}
}
若要了解可用于语言提取程序的选项,请输入:
-
codeql resolve languages --format=betterjson或 -
codeql resolve extractor --format=betterjson。
betterjson 输出格式还提供提取程序的根和其他特定于语言的选项。
CodeQL 数据库中的数据
CodeQL 数据库是一个目录,其中包含分析所需的所有数据。 此数据包括关系数据、复制的源文件以及针对特定语言的数据库架构,该架构指定了数据中的相互关系。 CodeQL 在提取后导入此数据。
CodeQL 数据库提供从代码库中提取的特定语言可查询数据的快照。 此数据是代码的完整分层表示形式。 其中包括:
- 抽象语法树(AST)的表示形式。
- 数据流图。
- 控制流图。
对于多语言代码库,数据库一次生成一种语言。 每种语言都有自己的唯一数据库架构。 该架构在提取过程中提供初始词法分析与通过 CodeQL 进行复杂分析之间的接口。
CodeQL 数据库包括两个主要表:
- 表达式表包含 CodeQL 在生成过程中分析的源代码中每个表达式的一行。
- 语句表包含 CodeQL 在生成过程中分析的源代码中每个语句的一行。
CodeQL 库定义类,以便为每个表提供抽象层。 此层包括相关的辅助表 Expr 和 Stmt。
潜在的 CodeQL 缺陷
代码扫描工作流中的数据库创建存在一些潜在的不足。 本部分专门讨论如何使用 GitHub CodeQL 操作。
需要使用语言矩阵进行自动生成,以生成矩阵中列出的每个已编译语言。 可以使用矩阵为编程语言、作系统或工具的多个受支持的版本创建作业。
如果不使用矩阵,自动生成会尝试使用存储库中大多数源文件生成受支持的已编译语言。 在分析编译语言时(Go 除外),如果不在执行分析步骤之前提供显式命令生成代码,往往会导致分析失败。
自动生成步骤的行为因语言提取程序所运行的操作系统而异。 自动生成步骤尝试根据操作系统自动检测语言的合适生成方法。 此行为可能导致编译语言的不可靠结果,并且通常会导致运行失败。
我们建议您在代码扫描工作流文件中配置一个在分析前运行的构建步骤,而不是让 autobuild 尝试构建编译型语言项目。 这样,工作流文件根据您的系统和项目的构建需求进行了调整,以实现更可靠的扫描。
可以在 CodeQL 自动生成文档中详细了解特定语言和自动生成步骤。
VS Code 扩展
只要使用的是 VS Code 1.39 或更高版本,就可以使用 Visual Studio Code (VS Code)和 CodeQL 扩展来编译和运行查询。 可以从Visual Studio Code市场下载扩展,也可以下载 CodeQL VSIX 文件。
该扩展使用在 PATH 中找到的已安装 CLI(如果可用)。 如果没有,扩展将自动为你管理对 CLI 可执行文件的访问。 自动管理可确保 CLI 与 CodeQL 扩展兼容。