☰
GitHub Actions Code Scanning 起步工作流全解析:从 CodeQL 到第三方 SAST 的安全扫描矩阵
2026/10/2 7:53:59 网站建设 项目流程
  • 示例工程
  • CI/CD
  • DevOps

【免费下载链接】starter-workflows

Accelerating new GitHub Actions workflows

项目地址:https://gitcode.com/GitHub_Trending/st/starter-workflows
点击查看免费下载

本文基于starter-workflows仓库的 code-scanning 目录,系统讲解如何借助 GitHub Actions 工作流为仓库启用代码扫描(Code Scanning):从 GitHub 原生 CodeQL 到 Bandit、Trivy、Semgrep、Snyk 等第三方扫描器,再到依赖审查与供应链安全评分。读完本文,你将掌握 code scanning 的启用方式、工作流结构、SARIF 结果上传机制,以及一套可直接落地的安全扫描矩阵。

一、什么是 GitHub Code Scanning,为什么要用工作流启用它

GitHub Code Scanning 是一种"开发者优先、GitHub 原生"的安全能力,其核心目标是在漏洞到达生产环境之前尽早发现它们。starter-workflows仓库在 code-scanning/README.md 中明确指出一个关键前提:

在为一个仓库配置 Code Scanning 之前,必须先通过向仓库添加一个 GitHub Actions 工作流来启用它。

也就是说,Code Scanning 并非一个"打开开关"就生效的默认功能,而是以"工作流即配置"的形态存在的:扫描器(无论是 GitHub 官方出品的 CodeQL,还是第三方安全工具)都以 Action 的形式在 CI 流水线中运行,扫描结果通过 SARIF 格式上传回 GitHub 的 Security 标签页统一展示。

这正是本仓库code-scanning/目录的价值所在:它集中提供了近百个可以直接复制使用的 Code Scanning 起步工作流(starter workflow),覆盖:

  • GitHub 原生静态分析:CodeQL;
  • 语言级 SAST 工具:Bandit(Python)、ESLint(JavaScript/TypeScript)、RuboCop、detekt 等;
  • 依赖与供应链安全:Dependency Review、OSV-Scanner、Debricked、datree;
  • 镜像与基础设施扫描:Trivy、tfsec、kubesec、Checkov 系策略校验;
  • 综合安全平台:Snyk、Semgrep、SonarQube、Veracode、Fortify 等。

每个工作流都配套了对应元数据文件(code-scanning/properties/*.properties.json),描述其名称、创建者、适用语言与分类,例如 codeql.properties.json 声明 CodeQL 支持 C、C++、C#、Go、Java、JavaScript、TypeScript、Python、Ruby、Kotlin 与 Swift。

二、快速上手:把起步工作流变成仓库里的扫描任务

启用 Code Scanning 的实操路径是:从本仓库的 code-scanning 目录中选取合适的工作流文件,复制到你的仓库.github/workflows/目录下并提交。工作流一旦被提交到仓库,就会按照on声明的触发条件自动运行。

以最基础的触发结构为例,绝大多数起步工作流统一采用三种触发组合:

on: push: branches: [ main, protected-branches ] pull_request: branches: [ main ] schedule: - cron: '0 0 * * 0' # 每周定时扫描

这种设计覆盖了三种典型场景:

触发事件作用
push每次推送到默认/受保护分支时扫描,保证主分支代码始终处于被检查状态
pull_request每次 PR 时扫描,在合并前拦截新引入的漏洞(可与分支保护规则联动)
schedule定期重扫,捕获依赖更新后新暴露的 CVE,弥补"增量扫描"的盲区

关键权限约定

几乎所有工作流都在 job 级别声明了一组最小权限,例如 bandit.yml 与 trivy.yml 中的模式:

permissions: contents: read # 供 actions/checkout 拉取代码 security-events: write # 供 github/codeql-action/upload-sarif 上传 SARIF 结果 actions: read # 私有仓库中 upload-sarif 获取 Action 运行状态所需

其中security-events: write是 Code Scanning 的核心权限——没有它,扫描结果无法写入 GitHub 的 Security 标签页。

三、核心实战一:CodeQL —— GitHub 官方原生静态分析

CodeQL 是 GitHub 官方出品的语义代码分析引擎,其起步工作流位于 codeql.yml,文件头部注释明确提示:对大多数项目,该文件无需修改,只需提交到仓库即可运行;需要改动时,通常是调整被分析的语言集合,或提供自定义查询与构建逻辑。

3.1 工作流结构

name: "CodeQL Advanced" on: push: branches: [ $default-branch, $protected-branches ] pull_request: branches: [ $default-branch, $protected-branches ] schedule: - cron: $cron-weekly jobs: analyze: name: Analyze (${{ matrix.language }}) runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }} permissions: security-events: write packages: read actions: read contents: read strategy: fail-fast: false matrix: $codeql-languages-matrix

几个值得注意的工程细节:

  • 矩阵扫描:工作流通过strategy.matrix对每种语言分别运行一次分析(fail-fast: false保证某一种语言失败不会中断其他语言的分析);
  • 运行器选择:Swift 语言强制使用macos-latest,其余语言使用ubuntu-latest,注释提示考虑更大规格 runner 以缩短分析时间;
  • packages 权限:packages: read用于拉取内部或私有的 CodeQL packs(查询包)。

3.2 三步核心流程

CodeQL 分析由三个标准步骤组成:

steps: - name: Checkout repository uses: actions/checkout@v4 - name: Initialize CodeQL uses: github/codeql-action/init@v4 with: languages: ${{ matrix.language }} build-mode: ${{ matrix.build-mode }} # 可在此处或配置文件中指定自定义查询 # queries: security-extended,security-and-quality - name: Perform CodeQL Analysis uses: github/codeql-action/analyze@v4 with: category: "/language:${{matrix.language}}"
  • init:初始化 CodeQL 工具链并确定分析语言。默认查询集之外,可追加security-extended(扩展安全查询)或security-and-quality(安全 + 质量查询);
  • analyze:执行查询并产出结果,category按语言隔离结果分类。

3.3 编译型语言的手动构建模式

对于 C/C++、Java、Kotlin 等编译型语言,若 analyze 步骤报错 "We were unable to automatically build your code",工作流内置了build-mode: manual的兜底路径:在矩阵中为该语言设置手动构建模式后,执行一个由用户填充构建命令的步骤:

- name: Run manual build steps if: matrix.build-mode == 'manual' shell: bash run: | echo '请替换为构建代码的命令,例如:' echo ' make bootstrap' echo ' make release' exit 1

该步骤默认以exit 1提醒使用者必须填入真实构建命令,避免"空跑"。

四、核心实战二:按语言选型 —— Bandit 与 ESLint

4.1 Bandit:Python 安全 lint

bandit.yml 基于第三方 Actionshundor/python-bandit-scan运行 Bandit——一个专找 Python 常见安全问题的安全 linter,扫描结果同样出现在仓库 Security 标签页。其可配置参数非常丰富:

- name: Bandit Scan uses: shundor/python-bandit-scan@ab1d87dfccc5a0ffab88be3aaac6ffe35c10d6cd with: # exit with 0, even with results found exit_zero: true GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # path: # 扫描的文件或目录,默认 . # level: # 最低报告级别:LOW / MEDIUM / HIGH,默认 UNDEFINED(全部) # confidence: # 最低置信级别:LOW / MEDIUM / HIGH,默认 UNDEFINED(全部) # excluded_paths: # 排除路径(glob),默认排除 .git、__pycache__、.tox 等 # skips: # 跳过的测试 ID 列表 # ini_path: # 指向提供命令行参数的 .bandit 文件

通过level与confidence组合,可以方便地实现"只关注 HIGH 级别高置信问题"的降噪策略。

4.2 ESLint:JavaScript/TypeScript 静态规则检查

eslint.yml 展示了"传统 lint 工具 + SARIF 格式化 + 上传"的通用接入模式:

- name: Install ESLint run: | npm install eslint@8.10.0 npm install @microsoft/eslint-formatter-sarif@3.1.0 - name: Run ESLint env: SARIF_ESLINT_IGNORE_SUPPRESSED: "true" run: npx eslint . --config .eslintrc.js --ext .js,.jsx,.ts,.tsx --format @microsoft/eslint-formatter-sarif --output-file eslint-results.sarif continue-on-error: true - name: Upload analysis results to GitHub uses: github/codeql-action/upload-sarif@v3 with: sarif_file: eslint-results.sarif wait-for-processing: true

关键点:ESLint 本身不是安全扫描器,但通过@microsoft/eslint-formatter-sarif将结果格式化为 SARIF 后,就能借助upload-sarif统一汇入 GitHub 的 Code Scanning 面板。continue-on-error: true保证 lint 报错不阻断 CI,wait-for-processing: true则让上传步骤等待 GitHub 处理完成。

五、核心实战三:镜像与基础设施扫描 —— Trivy

trivy.yml 是容器镜像漏洞扫描的完整范例,流程为"构建镜像 → 扫描 → 上传 SARIF":

- name: Build an image from Dockerfile run: | docker build -t docker.io/my-organization/my-app:${{ github.sha }} . - name: Run Trivy vulnerability scanner uses: aquasecurity/trivy-action@7b7aa264d83dc58691451798b4d117d53d21edfe with: image-ref: 'docker.io/my-organization/my-app:${{ github.sha }}' format: 'template' template: '@/contrib/sarif.tpl' output: 'trivy-results.sarif' severity: 'CRITICAL,HIGH' - name: Upload Trivy scan results to GitHub Security tab uses: github/codeql-action/upload-sarif@v3 with: sarif_file: 'trivy-results.sarif'

这里image-ref复用前面构建的镜像 tag(${{ github.sha }}保证唯一性),severity: 'CRITICAL,HIGH'过滤出高危及以上问题,format: 'template'配合@/contrib/sarif.tpl把扫描结果转成 SARIF。这也是容器类扫描的通用范式:Dockerfile → 构建 → 扫描 → 上传。

六、核心实战四:依赖与供应链安全

6.1 OSV-Scanner:开源漏洞数据库扫描

osv-scanner.yml 展示了一个"复用型工作流 + 双场景分流"的精巧设计:它通过google/osv-scanner-action提供的 reusable workflow 同时处理两类任务:

jobs: scan-scheduled: if: ${{ github.event_name == 'push' || github.event_name == 'schedule' }} uses: "google/osv-scanner-action/.github/workflows/osv-scanner-reusable.yml@1f1242919d8a60496dd1874b24b62b2370ed4c78" # v1.7.1 with: scan-args: |- -r --skip-git ./ scan-pr: if: ${{ github.event_name == 'pull_request' || github.event_name == 'merge_group' }} uses: "google/osv-scanner-action/.github/workflows/osv-scanner-reusable-pr.yml@1f1242919d8a60496dd1874b24b62b2370ed4c78" # v1.7.1 with: scan-args: |- -r --skip-git ./
  • 定时/推送扫描:全量扫描仓库(-r递归、--skip-git跳过 git 内部文件);
  • PR/merge_group 扫描:使用专用的 PR 复用工作流,只检查本次变更是否引入新漏洞,实现"增量拦截"。

6.2 Dependency Review:PR 合并前的依赖闸门

dependency-review.yml 针对 PR 中变更的依赖清单文件(manifest)进行审查,当 PR 引入已知漏洞版本时,可作为 required check 阻止合并:

- name: 'Dependency Review' uses: actions/dependency-review-action@v4 with: comment-summary-in-pr: always # fail-on-severity: moderate # deny-licenses: GPL-1.0-or-later, LGPL-2.0-or-later # retry-on-snapshot-warnings: true

常用增强选项包括fail-on-severity(按严重级别失败)、deny-licenses(拒绝特定许可证,实现许可证合规门禁)、retry-on-snapshot-warnings。注意其权限要求:若同时使用依赖提交(Dependency Submission)API,contents权限需提升为write。

6.3 Scorecard:供应链安全评分

scorecard.yml 集成 OpenSSF Scorecard,为仓库的供应链安全实践打分。它的触发方式极具特色——专门监听branch_protection_rule事件(分支保护变更)以保证 Branch-Protection 检查的实时性,同时辅以每周定时任务维持 Maintained 检查的更新:

on: branch_protection_rule: schedule: - cron: $cron-weekly push: branches: [ $default-branch ]

核心步骤:

- name: "Run analysis" uses: ossf/scorecard-action@f49aabe0b5af0936a0987cfb85d86b75731b0186 # v2.4.1 with: results_file: results.sarif results_format: sarif # repo_token: ${{ secrets.SCORECARD_TOKEN }} # 私有仓库/公开仓库启用 Branch-Protection 检查时按需配置 publish_results: true # 仅默认分支运行;私有仓库恒为 false

随后通过actions/upload-artifact将 SARIF 作为构建产物留存(retention-days: 5),并可选上传到 code-scanning 面板。若要在私有仓库启用 Branch-Protection 检查,需要配置 fine-grained PAT 形式的repo_token。

七、综合平台接入 —— Semgrep 与 Snyk

7.1 Semgrep:规则可管理的 SAST 平台

semgrep.yml 需要先在 Semgrep.dev 注册免费账户以管理规则、文件忽略与通知:

- uses: returntocorp/semgrep-action@fcd5ab7459e8d91cb1777481980d1b18b4fc6735 with: publishToken: ${{ secrets.SEMGREP_APP_TOKEN }} publishDeployment: ${{ secrets.SEMGREP_DEPLOYMENT_ID }} generateSarif: "1" - name: Upload SARIF file uses: github/codeql-action/upload-sarif@v3 with: sarif_file: semgrep.sarif if: always()

generateSarif: "1"指示 Action 生成 SARIF 文件,上传步骤加if: always()确保即使扫描发现问题也照常上传。

7.2 Snyk:全平台四合一扫描

snyk-security.yml 是覆盖面最广的范例,一次工作流同时调用 Snyk Open Source(SCA)、Snyk Code(SAST)、Snyk Container 与 Snyk IaC 四个引擎:

- name: Set up Snyk CLI uses: snyk/actions/setup@806182742461562b67788a64410098c9d9b96adb env: SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }} - name: Snyk Code test run: snyk code test --sarif > snyk-code.sarif # 追加 || true 可避免阻断流水线 - name: Snyk Open Source monitor run: snyk monitor --all-projects - name: Snyk IaC test and report run: snyk iac test --report - name: Build a Docker image run: docker build -t your/image-to-test . - name: Snyk Container monitor run: snyk container monitor your/image-to-test --file=Dockerfile - name: Upload result to GitHub Code Scanning uses: github/codeql-action/upload-sarif@v3 with: sarif_file: snyk-code.sarif

要点:

  • snyk code test --sarif将 SAST 结果输出为 SARIF 文件,最后一步上传到 GitHub Code Scanning;
  • snyk monitor将依赖与镜像结果上报到 Snyk 平台侧持续跟踪;
  • 使用 Snyk Open Source 前需先配置好开发环境(如actions/setup-node)。

八、贯通全目录:一次看懂仓库的扫描器全景

code-scanning/目录中每个.yml与其同名.properties.json一一对应,后者为工作流提供面向 UI 的元信息(名称、创建者、描述、语言分类)。从目录清单可以梳理出四大接入范式:

范式一:GitHub 原生三步式—— CodeQL 的checkout → init → analyze,以及任何工具产出的 SARIF 文件最终都经由github/codeql-action/upload-sarif@v3统一上传,这是全目录最通用的收尾步骤(见 codeql.yml、trivy.yml、eslint.yml、semgrep.yml 等)。

范式二:独立 CLI + SARIF 上传—— 工具以 CLI/命令方式运行,手动将结果转成 SARIF 再上传,代表有 ESLint、Snyk Code。

范式三:可复用工作流(reusable workflow)—— 通过uses: <owner>/<repo>/.github/workflows/*.yml@<ref>直接调用上游定义好的扫描流程,代表有 OSV-Scanner(osv-scanner.yml)。

范式四:平台托管 Action—— 通过第三方 Action 封装完整扫描逻辑,配合with:参数化配置,代表有 Bandit(bandit.yml)、Semgrep、Scorecard(scorecard.yml)。

其余工作流(如 anchore、checkmarx、sonarqube、veracode、fortify、trivy、tfsec、kubesec、osv-scanner、dependency-review 等)均可在 code-scanning 目录中直接查阅,覆盖语言静态分析、容器、IaC、供应链等全部扫描维度。

九、落地建议与踩坑提醒

综合以上工作流源码,给出几条可直接照搬的实践建议:

  1. 先提交,再调参:如 codeql.yml 头部注释所言,大多数工作流直接提交即可运行;提交后务必核对矩阵中的语言集合与仓库实际语言一致。
  2. 权限最小化:统一采用contents: read+security-events: write+(私有仓库)actions: read的权限组合,仅在确有必要时放宽(如 Dependency Review 的pull-requests: write、Dependency Submission 场景的contents: write)。
  3. SARIF 是通用语言:无论扫描器来自哪家,最终都以 SARIF 上传到 GitHub Security 标签页,因此"第三方工具 + upload-sarif"是最可复用的集成路径。
  4. 定时扫描别省:schedule事件是捕获"依赖更新后新暴露漏洞"的关键,建议保留每周一次的$cron-weekly频率。
  5. 避免"空跑"与"误伤":手动构建模式的占位步骤以exit 1强制填写;需要降噪时通过severity、level/confidence、fail-on-severity等参数收紧关注范围,或按需追加|| true避免扫描失败阻断发布流水线。

最后提醒:本仓库的code-scanning/目录是起步模板集,实际接入时请以你的仓库语言、依赖形态与合规要求为准进行裁剪;扫描结果始终以仓库 Security 标签页展示的 SARIF 报告为最终依据。

  • 示例工程
  • CI/CD
  • DevOps

【免费下载链接】starter-workflows

Accelerating new GitHub Actions workflows

项目地址:https://gitcode.com/GitHub_Trending/st/starter-workflows
点击查看免费下载
上一篇:探索Before After:一款强大的Flutter图像对比工具
下一篇:【免费下载】 Termux API 包使用教程

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询