GitHub Security:代码扫描与漏洞修复自动化流程

在软件交付速度越来越快的今天,安全检查不能再停留在发布前的人工抽查。更可靠的方式,是把代码扫描、依赖治理、密钥检测和合并门禁直接接入日常开发流程。

本文以 GitHub 原生能力为基础,介绍如何使用 CodeQL、Dependabot、Secret scanning 和 GitHub Actions,搭建一套“发现—分级—修复—验证—发布”的自动化安全流程。

一、整体流程

代码提交或定时任务

CodeQL / Dependabot / Secret scanning

生成安全告警或修复 PR

风险分级、分配负责人、设置 SLA

修复代码、升级依赖或轮换凭证

CI、回归测试和安全扫描验证

人工审查并合并

发布验证、关闭告警、复盘记录

这套流程的关键不是工具越多越好,而是让每个告警都能找到负责人、修复动作和验证结果。

二、启用 GitHub Security

进入仓库的 Settings > Advanced Security,根据仓库套餐和组织策略启用:

  • Dependabot alerts:识别依赖中的已知漏洞。
  • Dependabot security updates:针对可修复漏洞创建升级 PR。
  • Dependabot version updates:按计划维护普通依赖版本。
  • Code scanning:使用 CodeQL 分析源代码。
  • Secret scanning 和 Push protection:发现并阻止密钥泄露。

建议同时启用默认分支保护,将 CodeQL 和核心 CI 设置为 Required status checks,避免未通过安全检查的代码直接合并。

三、配置 CodeQL 代码扫描

创建 .github/workflows/codeql.yml:

name: CodeQL

on:
push:
branches: ["main"]
pull_request:
branches: ["main"]
schedule:
- cron: "23 2 * * 1"
workflow_dispatch:

permissions:
contents: read

jobs:
analyze:
name: Analyze (${{ matrix.language }})
runs-on: ubuntu-latest
permissions:
contents: read
security-events: write
pull-requests: read
strategy:
fail-fast: false
matrix:
language: ["javascript-typescript", "python"]

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

- name: Initialize CodeQL
uses: github/codeql-action/init@v4
with:
languages: ${{ matrix.language }}
queries: security-extended

- name: Autobuild
uses: github/codeql-action/autobuild@v4

- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v4

配置时需要注意:

  1. languages 只填写仓库实际使用的语言。
  2. Java、C/C++、C#、Go 等编译型项目,应确保分析前完成真实构建。
  3. 多语言项目使用矩阵分别分析,避免结果互相覆盖。
  4. security-extended 能扩大规则覆盖范围,但也可能增加误报排查成本。
  5. 不要在不可信 PR 中运行带有高权限的脚本,尤其要谨慎使用 pull_request_target。

四、配置 Dependabot

创建 .github/dependabot.yml:

version: 2
updates:
- package-ecosystem: npm
directory: "/"
schedule:
interval: weekly
open-pull-requests-limit: 10
groups:
npm-updates:
dependency-type: production
update-types:
- minor
- patch

- package-ecosystem: github-actions
directory: "/"
schedule:
interval: weekly

Dependabot alerts 负责报告漏洞,Security updates 负责创建安全升级 PR,Version updates 负责按计划维护普通依赖。Dependabot 不能替代构建、测试和人工审查,不应因为 PR 来自 Dependabot 就直接自动合并。

五、建立安全合并门禁

建议将构建、CodeQL、锁文件一致性、SAST、Lint 和许可证检查设置为默认分支的 Required status checks。

风险等级建议时限处理要求
Critical / High立即或 24 小时内优先修复,必要时暂停发布
Medium一个迭代周期内指定负责人和截止时间
Low纳入定期治理评估误报、技术债和修复价值

历史告警可以分批治理,但不能把全部历史问题一次性关闭为误报。每次关闭都应填写真实原因和验证依据。

六、漏洞修复方法

修复代码漏洞

  1. 确认规则、文件位置、数据源、传播路径和危险汇点。
  2. 判断问题是真实漏洞、不可达代码还是误报。
  3. 修复完整数据流,而不是简单删除触发告警的代码行。
  4. 对正常输入、边界输入和异常输入进行回归验证。
  5. 在 PR 中记录根因、影响范围、修复方式和验证结果。
  6. 合并后确认默认分支的告警已经关闭。

修复依赖漏洞

  1. 查看受影响版本、修复版本和依赖引入路径。
  2. 优先使用安全升级 PR;存在破坏性升级时先完成兼容改造。
  3. 更新锁文件,执行安装、构建、启动和回归验证。
  4. 检查新的传递依赖、许可证变化和供应链风险。
  5. 合并后确认告警状态,并验证生产环境实际使用的版本。

处理密钥泄露

发现真实 API Key、密码或云凭证后,应立即撤销或轮换,检查访问日志,从当前代码中移除密钥,并迁移到 GitHub Secrets 或正式密钥管理系统。最后记录泄露时间、影响范围、轮换结果和改进措施。

七、Actions 安全基线

  • 顶层默认使用 permissions: contents: read,只在具体 job 中增加必要权限。
  • 第三方 Action 应使用可信来源;高安全要求项目可固定到完整 commit SHA。
  • 不要把 Issue 标题、PR 标题等不可信文本直接拼接到 run shell 命令。
  • 不在日志中打印令牌、密码、连接字符串和完整请求头。
  • 生产部署优先使用环境审批和 OIDC 短期凭证,避免长期云密钥。
  • 不将包含敏感数据的构建产物上传到 Actions。

八、Windows PowerShell 验证

提交配置前执行:

git diff --check
git status --short
Get-Content .github\\workflows\\codeql.yml -Raw
Get-Content .github\\dependabot.yml -Raw

提交后,在 GitHub Actions 和 Security 页面确认 CodeQL 能在 push、PR 和定时任务中启动,Dependabot 能读取依赖清单,Required checks 能阻止失败 PR 合并,修复后的告警能在默认分支重新扫描后关闭。

九、回滚与风险接受

如果依赖升级造成构建或生产异常,应回滚到已验证的安全版本,保留失败日志和原 Dependabot PR,建立兼容性修复分支并重新执行完整 CI。无法立即修复时,记录风险接受人、到期时间和补偿控制措施。

十、日常运营清单

每次 PR

  • [ ] CodeQL 和 Required checks 通过。
  • [ ] 依赖锁文件与清单一致。
  • [ ] 没有新增密钥告警。
  • [ ] 安全相关变更完成人工审查。

每周

  • [ ] 处理 Critical/High 告警和 Dependabot 安全 PR。
  • [ ] 检查失败的 CodeQL、Dependabot 和 Actions 任务。
  • [ ] 审查新增依赖、第三方 Action 和权限变更。

每月

  • [ ] 统计告警数量、平均修复时长和超期项。
  • [ ] 清理过期例外和风险接受记录。
  • [ ] 验证分支保护、Secrets、环境审批和组织安全策略。

结语

安全自动化的价值,不是让扫描工具替开发者做决定,而是把安全检查放到最接近代码变更的位置,并让每个问题都拥有清晰的责任人、修复路径和验证结果。

当 CodeQL 负责代码质量,Dependabot 负责依赖更新,Secret scanning 负责凭证保护,再配合 CI 和分支保护,GitHub 就能形成一条可持续运行的 DevSecOps 安全流水线。

参考资料