使用第三方工具启用代码扫描

已完成

你可以在其他位置执行分析,然后上传结果,而不是在 GitHub 中运行代码扫描。 在外部运行的代码扫描警报的显示方式与在 GitHub 中运行的警报相同。 你可以上传在 GitHub 外部或使用 GitHub Actions 生成的静态分析结果交换格式 (SARIF) 文件,以查看来自存储库中第三方工具的代码扫描警报。

此单元介绍如何使用第三方工具启用代码扫描,以及如何使用和上传 SARIF 文件。

关于代码扫描的 SARIF 文件上传

GitHub 使用 SARIF 文件中的信息在存储库中创建代码扫描警报。 可以使用多个静态分析安全测试工具(包括 CodeQL)来生成 SARIF 文件。 结果必须使用 SARIF 版本 2.1.0。

可以使用代码扫描 API、CodeQL CLI 或 GitHub Actions 上传结果。 最佳上传方法将取决于 SARIF 文件的生成方式。

代码扫描 API

通过代码扫描 API,可以从存储库检索有关代码扫描警报、分析、数据库和默认设置配置的信息。 此外,还可以更新代码扫描警报和默认设置配置。 你可以使用终结点为组织中的代码扫描警报创建自动报告,或上传使用离线代码扫描工具生成的分析结果。

可以通过 HTTPS 从 https://api.github.com 访问 GitHub API。 所有数据都以 JSON 格式发送和接收。 API 使用自定义媒体类型让消费者选择他们希望接收的数据格式。 媒体类型特定于资源,允许它们独立更改并支持其他资源不支持的格式。

代码扫描 REST API 支持一种自定义媒体类型 - application/sarif+json

可以将此媒体类型用于发送到 /analyses/{analysis_id} 终结点的 GET 请求。 将此媒体类型用于此操作时,响应包括为指定分析上传的实际数据的子集,而不是使用默认媒体类型时返回的分析摘要。 响应还包括其他数据,如 github/alertNumbergithub/alertUrl 属性。 数据的格式为 SARIF 版本 2.1.0。

下面是使用 API 列出组织代码扫描警报的示例 cURL 命令:

curl -L \
  -H "Accept: application/vnd.github+json" \
  -H "Authorization: Bearer <YOUR-TOKEN>" \
  -H "X-GitHub-Api-Version: 2022-11-28" \
  https://api.github.com/orgs/ORG/code-scanning/alerts

有关使用代码扫描 API 的详细信息,请查看GitHub REST API 文档

CodeQL命令行界面 (CLI)

CodeQL CLI 是一个独立的产品,可用于分析代码。 其主要用途是生成代码库的数据库表示,即 CodeQL 数据库。 数据库准备就绪后,可以以交互方式对其进行查询,也可以运行一组查询,以 SARIF 格式生成一组结果,并将结果上传到 GitHub.com。 CodeQL命令行界面可用于在GitHub.com上维护的公共存储库。对于客户拥有的专用存储库,需持有高级安全许可证才能使用。 从 https://github.com/github/codeql-action/releases 下载 CodeQL 捆绑包。

该捆绑包中包含:

应始终使用 CodeQL 捆绑包,因为这样可确保兼容性,并且性能比单独下载 CodeQL CLI 和签出 CodeQL 查询要好。

使用 GitHub Actions 进行代码扫描分析

若要使用 GitHub Actions 将第三方 SARIF 文件上传到存储库,需要 GitHub Actions 工作流。 GitHub Actions 工作流是一个自动化流程,由一个或多个作业组成,配置为 .yml 文件。 工作流存储在存储库的 .github/workflows 目录中。

工作流使用 upload-sarif 操作,是 github/codeql-action 存储库的一部分。 此工作流包含可用于配置上传的输入参数。

主输入参数为 sarif-file,它配置要上传的 SARIF 文件的文件或目录。 目录或文件路径相对于存储库的根目录。

upload-sarif 操作可以配置为在 pushscheduled 事件发生时运行。

此示例概述了 upload-sarif 操作 yml 文件的元素:

name: 'Code Scanning : Upload SARIF'
description: 'Upload the analysis results'
author: 'GitHub'
inputs:
  sarif_file:
    description: |
      The SARIF file or directory of SARIF files to be uploaded to GitHub code scanning.
      See https://docs.github.com/en/code-security/code-scanning/integrating-with-code-scanning/
      uploading-a-sarif-file-to-github#uploading-a-code-scanning-analysis-with-github-actions
      for information on the maximum number of results and maximum file size supported by code scanning.
    required: false
    default: '../results'
  checkout_path:
    description: "The path at which the analyzed repository was checked out. 
    Used to relativize any absolute paths in the uploaded SARIF file."
    required: false
    default: ${{ github.workspace }}
  token:
    default: ${{ github.token }}
  matrix:
    default: ${{ toJson(matrix) }}
  category:
    description: String used by Code Scanning for matching the analyses
    required: false
  wait-for-processing:
    description: If true, the Action will wait for the uploaded SARIF to be processed before completing.
    required: true
    default: "false"
runs:
  using: 'node12'
  main: '../lib/upload-sarif-action.js' 

每次上传新代码扫描的结果时,都会处理结果并将警报添加到存储库中。 GitHub 使用 SARIF 文件中的属性来显示警报。 例如,为了防止同一问题出现重复警报,代码扫描使用指纹来匹配各种运行中的结果,因此它们仅在所选分支的最新运行中出现一次。 CodeQL 分析工作流创建的 SARIF 文件在 partialFingerprints 字段中包含此指纹数据。 如果使用 upload-sarif 操作上传 SARIF 文件并且此数据丢失,GitHub 会尝试从源文件填充 partialFingerprints 字段。

如果你的 SARIF 文件不包含 partialFingerprints,则 upload-sarif 操作将为你计算 partialFingerprints 字段并尝试防止重复警报。 只有当存储库同时包含 SARIF 文件和静态分析中使用的源代码时,GitHub 才能创建 partialFingerprints

SARIF 上传支持每次上传最多 5,000 条结果。 任何超过此限制的结果都将被忽略。 如果工具生成太多结果,则应更新配置,以将重点放在最重要的规则或查询的结果上。

对于每次上传,SARIF 上传支持最大大小为 10 MB 的 gzip 压缩 SARIF 文件。 任何超过此限制的上传都将被拒绝。 如果 SARIF 文件由于包含太多结果而过大,则应更新配置,以将重点放在最重要的规则或查询的结果上。

上传在存储库外部生成的 SARIF 文件

你还可以创建一个新的工作流,在将 SARIF 文件提交到存储库后上传这些文件。 当 SARIF 文件作为存储库外部的工件生成时,这很有用。

在下面的示例中,只要将提交推送到存储库,就会运行工作流。 操作使用 partialFingerprints 属性来确定是否发生了更改。

除了在推送提交时运行,工作流计划为每周运行一次。 此工作流上传位于存储库根目录中的 results.sarif 文件。 你还可以修改此工作流以上传 SARIF 文件的目录。 例如,您可以将所有 SARIF 文件放在存储库根目录中名为 sarif-output 的目录中,并将操作的输入参数 sarif_file 设置为 sarif-output

name: "Upload SARIF"

// Run workflow each time code is pushed to your repository and on a schedule. 
//The scheduled workflow runs every Thursday at 15:45 UTC.

on:
  push:
  schedule:
    - cron: '45 15 * * 4'

jobs:
  build:
    runs-on: ubuntu-latest
    permissions:
      security-events: write
  steps:
    # This step checks out a copy of your repository.
    - name: Checkout repository
      uses: actions/checkout@v2
    - name: Upload SARIF file
      uses: github/codeql-action/upload-sarif@v1
      with:
        # Path to SARIF file relative to the root of the repository
        sarif_file: results.sarif 

上传在 CI 工作流中生成的 SARIF 文件

如果在持续集成 (CI) 工作流中生成第三方 SARIF 文件,则可以在运行 CI 测试后将 upload-sarif 操作添加为一个步骤。 如果还没有 CI 工作流,可以使用 https://github.com/actions/starter-workflows 存储库中的入门工作流创建一个。

在此示例中,只要将提交推送到存储库,就会运行工作流。 操作使用 partialFingerprints 属性来确定是否发生了更改。 除了在推送提交时运行,工作流计划为每周运行一次。

此示例将 ESLint 静态分析工具显示为工作流中的一个步骤。 Run ESLint 步骤运行 ESLint 工具并输出 results.sarif 文件。 然后,工作流使用 results.sarif 操作将 upload-sarif 文件上传到 GitHub。

  ```
  name: "ESLint analysis"

// Run workflow each time code is pushed to your repository and on a schedule.
// The scheduled workflow runs every Wednesday at 15:45 UTC.
on:
  push:
  schedule:
    - cron: '45 15 * * 3'

jobs:
  build:
    runs-on: ubuntu-latest
    permissions:
      security-events: write
    steps:
      - uses: actions/checkout@v2
      - name: Run npm install
        run: npm install
      // Runs the ESlint code analysis
      - name: Run ESLint
        // eslint exits 1 if it finds anything to report
        run: node_modules/.bin/eslint build docs lib script spec-main -f node_modules/@microsoft/eslint-formatter-sarif/sarif.js -o results.sarif || true
      // Uploads results.sarif to GitHub repository using the upload-sarif action
      - uses: github/codeql-action/upload-sarif@v1
        with:
          // Path to SARIF file relative to the root of the repository
          sarif_file: results.sarif
  ```