Skip to main content
We publish frequent updates to our documentation, and translation of this page may still be in progress. For the most current information, please visit the English documentation.

对 CodeQL 的高级设置进行故障排除

如果 code scanning 的高级设置出现问题,可以使用以下用于解决问题的提示来进行故障排除。

Code scanning 可用于 GitHub.com 上的所有公共存储库。 若要在组织拥有的专用存储库中使用 code scanning,必须具有 GitHub Advanced Security 许可证。 有关详细信息,请参阅“关于 GitHub Advanced Security”。

注意:对于专用和内部存储库,code scanning 在对该资源库启用了 GitHub Advanced Security 功能时可用。 如果看到错误 Advanced Security must be enabled for this repository to use code scanning,请检查 GitHub Advanced Security 是否已启用。 有关详细信息,请参阅“管理存储库的安全和分析设置”。

生成详细的调试日志

要生成更详细的日志输出,您可以启用步骤调试日志记录。 有关详细信息,请参阅“启用调试日志记录”。

创建 CodeQL 调试工件

可以获取生成工件来帮助你调试 CodeQL。 调试工件作为名为 debug-artifacts 的工件上传到工作流运行。 数据包含 CodeQL 日志、 CodeQL 数据库以及工作流程生成的任何 SARIF 文件。

这些生成工件将帮助你调试 CodeQL code scanning 的问题。 如果您联系 GitHub 支持人员,他们可能会要求您提供此数据。

通过重新运行启用调试日志记录的作业来创建 CodeQL 调试生成工件

可以通过启用调试日志记录和重新运行作业来创建 CodeQL 调试生成工件。 有关重新运行 GitHub Actions 工作流和作业的详细信息,请参阅“重新运行工作流和作业”。

需要确保选择“启用调试日志记录”。 此选项将为运行启用运行器诊断日志记录和步骤调试日志记录。 然后你便可以下载 debug-artifacts 进行进一步调查。 通过重新运行作业创建 CodeQL 调试生成工件时,无需修改工作流文件。

创建 CodeQL 调试生成工件

可以通过在工作流中使用标志来创建 CodeQL 调试生成工件。 为此,需要修改 CodeQL analysis workflow 文件的 init 步骤并设置 debug: true

- name: Initialize CodeQL
  uses: github/codeql-action/init@v2
  with:
    debug: true

结果与预期不同

如果 code scanning 的结果与预期不同,则存储库可能同时具有默认和高级 code scanning 设置。 启用默认设置后,这会阻止存储库中任何 CodeQL 工作流文件上传结果。

若要检查是否启用了默认设置,请导航到存储库的主页,然后单击 “设置”。 在边栏的“安全性”部分,单击“代码安全性和分析”。 在页面的“Code scanning”部分中,单击“CodeQL 分析”旁边的 。 如果有 “切换到高级”选项,则当前使用的是默认设置。 若要切换到高级设置并从自定义工作流文件获取 code scanning 结果,请单击 “禁用 CodeQL”。 此选项将仅禁用默认设置,并且预先存在的工作流将再次开始上传结果。 有关详细信息,请参阅“为存储库配置 code scanning”。

编译语言的自动构建失败

如果项目中编译语言的代码自动构建失败,请尝试以下疑难解答步骤。

  • 从 code scanning 工作流中删除 autobuild 步骤,并添加特定构建步骤。 有关编辑工作流的信息,请参阅“自定义 code scanning”。 有关替换 autobuild 步骤的详细信息,请参阅“为已编译语言配置 CodeQL 工作流”。

  • 如果您的工作流程未明确指定要分析的语言,则 CodeQL 会隐式检测代码库中支持的语言。 在此配置中,对于编译语言 C/C++、C#、Go 和 Java,CodeQL 只分析源文件最多的语言。 编辑工作流并添加一个矩阵,以指定要分析的语言。 默认的 CodeQL 分析工作流将使用此类矩阵。

    以下工作流程摘录显示了如何在作业策略中使用矩阵来指定语言,然后在“初始化 CodeQL”步骤中引用每种语言:

    jobs:
      analyze:
        permissions:
          security-events: write
          actions: read
        ...
        strategy:
          fail-fast: false
          matrix:
            language: ['csharp', 'cpp', 'javascript']
    
        steps:
        ...
          - name: Initialize CodeQL
            uses: github/codeql-action/init@v2
            with:
              languages: ${{ matrix.language }}
    

    有关编辑工作流的详细信息,请参阅“自定义 code scanning”。

构建过程中找不到代码

如果工作流失败并出现错误 No source code was seen during the buildThe process '/opt/hostedtoolcache/CodeQL/0.0.0-20200630/x64/codeql/codeql' failed with exit code 32,则表示 CodeQL 无法监视代码。 有几个原因可以解释这种失败:

  1. 存储库可能不包含以 CodeQL 支持的语言编写的源代码。 检查受支持的语言列表,如果是这种情况,请删除 CodeQL 工作流。 有关详细信息,请参阅“关于使用 CodeQL 进行 code scanning”。

  2. 自动语言检测发现了受支持的语言,但仓库中没有该语言的可分析代码。 一个典型的例子是,我们的语言检测服务发现了一个与特定的编程语言相关的文件,例如 .h.gyp 文件,但存储库中没有相应的可执行代码。 要解决此问题,可通过更新 language 矩阵中的语言列表来手动定义要分析的语言。 例如,以下配置将仅分析 Go 和 JavaScript。

    strategy:
      fail-fast: false
      matrix:
        # Override automatic language detection by changing the list below.
        # Supported options are listed in a comment in the default workflow.
        language: ['go', 'javascript']
    

    有关详细信息,请参阅上述“编译语言的自动生成失败”中的工作流提取。

  3. code scanning 工作流正在分析一种编译语言(C、C++、C#、Go 或 Java),但代码尚未编译。 默认情况下,CodeQL 分析工作流包含 autobuild 步骤,但是,此步骤是一个尽力而为的过程,可能无法成功构建你的代码,具体取决于你的特定构建环境。 如果你删除了 autobuild 步骤但没有手动添加构建步骤,编译也可能会失败。 有关指定构建步骤的详细信息,请参阅“为已编译语言配置 CodeQL 工作流”。

  4. 工作流正在分析一种编译语言(C、C++、C#、Go 或 Java),但构建的某些部分会缓存以提高性能(最有可能发生在 Gradle 或 Bazel 等构建系统中)。 因为 CodeQL 观察编译器的活动以了解仓库中的数据流,因此 CodeQL 需要进行完整的构建才能执行分析。

  5. 工作流正在分析一种编译语言(C、C++、C#、Go 或 Java),但编译不会在工作流中的 initanalyze 步骤之间进行。 CodeQL 需要这两个步骤之间发生构建以观察编译器的活动并执行分析。

  6. 编译代码(使用 C、C++、C#、Go 或 Java)已成功编译,但 CodeQL 未能检测到编译器调用。 最常见原因是:

    • 在独立于 CodeQL 的容器中运行构建过程。 有关详细信息,请参阅“在容器中运行 CodeQL code scanning”。
    • 使用 GitHub Actions 外部的分布式构建系统,使用守护进程构建。
    • CodeQL 不知道您使用的特定编译器。

    对于 .NET Framework 项目以及使用 dotnet buildmsbuild 的 C# 项目,应在构建代码时在工作流的 run 步骤中指定 /p:UseSharedCompilation=false

    例如,以下 C# 的配置将在第一个构建步骤中传递标志。

    - run: |
        dotnet build /p:UseSharedCompilation=false
    

    如果您在特定编译器或配置方面遇到其他问题,请联系 GitHub Support

有关指定构建步骤的详细信息,请参阅“为已编译语言配置 CodeQL 工作流”。

扫描的代码行数低于预期

对于 C/C++、C#、Go 和 Java 等编译语言,CodeQL 仅扫描在分析过程中生成的文件。 因此,如果某些源代码未正确编译,则扫描的代码行数将低于预期。 这可能是多种原因引起的:

  1. CodeQL autobuild 功能使用启发式方法在存储库中生成代码。 但是,有时这种方法会导致对存储库的分析不完整。 例如,当单个存储库中存在多个 build.sh 命令时,分析可能不完整,因为 autobuild 步骤将仅执行其中一个命令,因此可能无法编译某些源文件。
  2. 某些编译器无法使用 CodeQL ,因此在分析代码时可能会导致问题。 例如,Lombok 项目使用非公共编译器 API 来修改编译器行为。 这些编译器修改中使用的假设不适用于 CodeQL 的 Java 提取器,因此无法分析代码。

如果 CodeQL 分析扫描的代码行数少于预期,则可以尝试使用多种方法来确保编译了所有必需的源文件。

替换 autobuild 步骤

autobuild 步骤替换为将在生产中使用的相同生成命令。 这可以确保 CodeQL 确切地知道如何编译要扫描的所有源文件。 有关详细信息,请参阅“为已编译语言配置 CodeQL 工作流”。

检查 CodeQL 数据库中源文件的副本

您可以通过检查 CodeQL 数据库中包含的源代码副本来了解为什么没有分析某些源文件。 要从 Actions 工作流中获取数据库,请修改 CodeQL 工作流文件的 init 步骤,并设置 debug: true

- name: Initialize CodeQL
  uses: github/codeql-action/init@v2
  with:
    debug: true

这会将数据库作为操作构件上传,您可以将其下载到本地计算机。 有关详细信息,请参阅“存储工作流工件”。

该构件将包含由名为 src.zip 的 CodeQL 扫描的源文件存档副本。 如果比较存储库中的源代码文件和 src.zip 中的文件,则可以看到缺少哪些类型的文件。 一旦您知道了哪些类型的文件没有被分析,就更容易理解了如何更改 CodeQL 分析的工作流程。

在生成的代码中找到的警报

对于 Java、Kotlin、Go、C、C++ 和 C# 等编译语言,CodeQL 分析在工作流运行过程中生成的所有代码。 要限制要分析的代码量,请通过在 run 块中指定自己的生成步骤,仅生成要分析的代码。 可以将指定自己的生成步骤与对 pull_requestpush 事件使用 pathspaths-ignore 筛选器相结合,以确保工作流仅在特定代码更改时运行。 有关详细信息,请参阅 GitHub Actions 的工作流语法

对于 JavaScript、Python,和 TypeScript 等语言,CodeQL 分析而不编译源代码,你可以指定其他配置选项来限制要分析的代码量。 有关详细信息,请参阅“自定义 code scanning”。

数据库中的提取错误

CodeQL 团队不断处理关键的提取错误,以确保可以扫描所有源文件。 但是,CodeQL 提取程序偶尔会在数据库创建过程中生成错误。 CodeQL 提供有关在日志文件中创建数据库期间生成的提取错误和警告的信息。 提取诊断信息指示数据库的整体运行状况。 大多数提取程序错误不会显著影响分析。 少量提取程序错误是正常的,通常表示分析状态良好。

但是,如果在数据库创建期间编译的绝大多数文件中看到提取程序错误,则应更详细地查看这些错误,以尝试了解为什么某些源文件未正确提取。

构建耗时过长

如果使用 CodeQL 分析进行的构建花费的时间太长,则可以尝试几种方法来减少构建时间。

增加内存或内核

如果使用自托管运行器运行 CodeQL 分析,您可以增加这些运行器上的内存或内核数。

使用矩阵构建来并行化分析

默认 CodeQL analysis workflow 使用语言矩阵,这会导致每种语言的分析并行运行。 如果在“初始化 CodeQL”步骤中指定了要直接分析的语言,则将依次进行每种语言的分析。 要加快对多种语言的分析,请修改工作流程以使用矩阵。 有关详细信息,请参阅上述“编译语言的自动生成失败”中的工作流提取。

减少单个工作流程中要分析的代码量

分析时间通常与所分析的代码量成正比。 您可以通过减少一次分析的代码量来缩短分析时间,例如,排除测试代码,或将分析分解为多个工作流程,这些工作流程一次只分析一部分代码。

对于 Java、Kotlin、Go、C、C++ 和 C# 等编译语言,CodeQL 分析在工作流运行过程中生成的所有代码。 要限制要分析的代码量,请通过在 run 块中指定自己的生成步骤,仅生成要分析的代码。 可以将指定自己的生成步骤与对 pull_requestpush 事件使用 pathspaths-ignore 筛选器相结合,以确保工作流仅在特定代码更改时运行。 有关详细信息,请参阅 GitHub Actions 的工作流语法

对于 JavaScript、Python,和 TypeScript 等语言,CodeQL 分析而不编译源代码,你可以指定其他配置选项来限制要分析的代码量。 有关详细信息,请参阅“自定义 code scanning”。

如果你按上文所述将分析拆分为多个工作流,我们仍然建议你至少保留一个按 schedule 运行的工作流分析存储库中的所有代码。 因为 CodeQL 分析组件之间的数据流量,所以某些复杂的安全行为只能在完整的构建中检测到。

仅在 schedule 事件期间运行

如果分析速度太慢,而无法在 pushpull_request 事件期间运行,建议仅在 schedule 事件上触发分析。 有关详细信息,请参阅“事件”。

检查工作流程运行的查询套件

默认情况下,每种语言都有三个主要查询套件可用。 如果已优化 CodeQL 数据库生成,但过程仍然太长,则可以减少运行的查询数。 默认查询套件将自动运行;它包含最快的安全查询,误报结果率最低。

除了默认查询之外,您可能还会运行额外的查询或查询套件。 检查工作流是否定义了其他查询套件或要使用 queries 元素运行的其他查询。 您可以尝试禁用其他一个或多个查询套件。 有关详细信息,请参阅“自定义 code scanning”。

注意: 如果运行 security-extended JavaScript 或 security-and-quality 查询套件,则某些查询使用实验技术。 有关详细信息,请参阅“关于 code scanning 警报”。

分析平台之间的结果差异

如果分析的是使用 Python 编写的代码,根据是在 Linux、macOS 还是 Windows 上运行 CodeQL analysis workflow,可能会看到不同的结果。

在使用 Linux 的 GitHub 托管运行器上,CodeQL analysis workflow 会尝试安装和分析 Python 依赖项,这可能生成更多结果。 若要禁用自动安装,请将 setup-python-dependencies: false 添加到工作流的“初始化 CodeQL”步骤。 有关配置 Python 依赖项分析的详细信息,请参阅“自定义 code scanning”。

错误:“服务器错误”

如果 code scanning 的工作流程运行因服务器错误而失败,请尝试再次运行工作流程。 如果问题仍然存在,请联系 GitHub Support

错误:“磁盘不足”或“内存不足”

在非常大的项目中, CodeQL 运行器上的磁盘或内存可能会耗尽。 如果你在托管的 GitHub Actions 运行器上遇到此问题,请联系 GitHub Support,以便我们对问题调查。

使用 Dependabot 时出现错误:403“集成无法访问资源”

Dependabot 在触发工作流运行时被视为不信任,工作流程将以只读范围运行。 为分支上传 code scanning 结果通常需要 security_events: write 范围。 但是,当 pull_request 事件触发操作运行时,code scanning 始终允许上传结果。 因此,对于 Dependabot 分支,建议使用 pull_request 事件,而不是 push 事件。

一个简单的方法是推送到默认分支和任何其他重要的长期分支,以及在此组分支上打开的拉取请求:

on:
  push:
    branches:
      - main
  pull_request:
    branches:
      - main

另一种方法是运行除 Dependabot 分支以外的所有推送:

on:
  push:
    branches-ignore:
      - 'dependabot/**'
  pull_request:

默认分支上的分析仍然失败

如果 CodeQL analysis workflow 在默认分支上的提交仍然失败,需要检查:

  • Dependabot 是否撰写了提交
  • 包含该提交的请求是否已使用 @dependabot squash and merge 进行合并

此类型的合并提交由 Dependabot 编写,因此在提交上运行的任何工作流程都将具有只读权限。 如果在存储库上启用了 code scanning 和 Dependabot 安全更新或版本更新,建议避免使用 Dependabot @dependabot squash and merge 命令。 不过,你可以为存储库启用自动合并。 这意味着,如果满足所有必需的评审并已通过状态检查,将自动合并拉取请求。 有关启用自动合并的详细信息,请参阅“自动合并拉取请求”。

错误:“不是 .ql 文件、.qls 文件、目录或查询包规范”

如果 CodeQL 在工作流中请求的位置找不到命名查询、查询套件或查询包,则会出现此错误。 此错误有两个常见的原因。

  • 工作流中有拼写错误。
  • 工作流通过路径引用的资源被重命名、删除或移动到新位置。

验证资源的位置后,可以更新工作流以指定正确的位置。

警告:“不再需要 git checkout HEAD^2”

如果您使用的是旧 CodeQL 工作流程,您可能会在输出中收到来自“初始化 CodeQL”操作的以下警告:

Warning: 1 issue was detected with this workflow: git checkout HEAD^2 is no longer
necessary. Please remove this step as Code Scanning recommends analyzing the merge
commit for best results.

通过从 CodeQL 工作流程中删除以下行来修复此问题。 这些行包含在 CodeQL 工作流初始版本中 Analyze 作业的 steps 部分。

        with:
          # We must fetch at least the immediate parents so that if this is
          # a pull request then we can checkout the head.
          fetch-depth: 2

      # If this run was triggered by a pull request event, then checkout
      # the head of the pull request instead of the merge commit.
      - run: git checkout HEAD^2
        if: ${{ github.event_name == 'pull_request' }}

修改后的工作流的 steps 部分将如下所示:

    steps:
      - name: Checkout repository
        uses: actions/checkout@v3

      # Initializes the CodeQL tools for scanning.
      - name: Initialize CodeQL
        uses: github/codeql-action/init@v2

      ...

有关编辑 CodeQL 工作流文件的详细信息,请参阅“自定义 code scanning”。