本文目录导读:

在CI/CD流水线中集成安全扫描,是为了实现 “安全左移” (将安全检测提前到开发阶段),从而以更低成本发现并修复漏洞。
以下是集成安全扫描的标准步骤、关键工具分类及具体集成方案(以GitHub Actions / GitLab CI / Jenkins为例)。
集成核心步骤
- 明确扫描类型:确定需要扫描哪些安全问题(见下文工具分类)。
- 选择工具:根据语言、框架和预算选择开源或商业工具。
- 集成到CI脚本:在构建、测试或部署阶段添加扫描命令。
- 定义失败策略:设置安全策略(发现
Critical级别漏洞则中断流水线)。 - 处理结果:将报告上传至平台,或通过插件自动创建Jira/GitLab Issue。
关键安全扫描类型与工具
| 扫描类型 | 说明 | 常用工具(开源/商业) | 集成阶段 |
|---|---|---|---|
| SAST(静态应用安全测试) | 白盒扫描源代码,发现SQL注入、XSS等。 | SonarQube, Semgrep, Checkmarx, Fortify | 代码提交后 / 构建前 |
| SCA(软件组成分析) | 扫描第三方依赖库,检测已知漏洞(CVE)。 | Trivy, Snyk, OWASP Dependency-Check, Black Duck | 依赖安装后 |
| 容器镜像扫描 | 扫描Docker镜像中的OS包和配置漏洞。 | Trivy, Clair, Anchore, Docker Scout | 镜像构建后 / 推送前 |
| DAST(动态应用安全测试) | 黑盒扫描运行中的应用。 | OWASP ZAP, Burp Suite, Acunetix | 部署至测试环境后 |
| IaC(基础设施即代码)扫描 | 扫描Terraform/K8s YAML中的错误配置。 | Checkov, tfsec, Terrascan | 代码提交时 |
| 密钥/凭证扫描 | 防止将API密钥、密码提交到仓库。 | GitLeaks, TruffleHog, GitGuardian | 每次Commit |
常见CI平台集成方案
方案1:在 GitHub Actions 中集成(最推荐)
name: Security Scan Pipeline
on: [push, pull_request]
jobs:
security-checks:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
# 1. SCA 依赖扫描 (使用 Trivy)
- name: Run Trivy vulnerability scanner for FS
uses: aquasecurity/trivy-action@master
with:
scan-type: 'fs' # 扫描文件系统
scan-ref: '.'
format: 'sarif' # 输出 SARIF 格式
output: 'trivy-results.sarif'
severity: 'CRITICAL,HIGH' # 只关注高危
exit-code: '1' # 发现漏洞则失败
# 2. SAST 代码扫描 (使用 Semgrep)
- name: Semgrep SAST scan
uses: semgrep/semgrep-action@v1
with:
config: p/default # 使用默认规则集
publishToken: ${{ secrets.SEMGREP_APP_TOKEN }}
auditOn: push
# 3. 密钥扫描
- name: GitLeaks Secret Scan
uses: gitleaks/gitleaks-action@v2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# 4. 上传 SARIF 报告到 GitHub Security 标签页
- name: Upload SARIF file
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: trivy-results.sarif
方案2:在 GitLab CI 中集成(原生支持)
# .gitlab-ci.yml
stages:
- build
- test
- security-scan
# 使用 GitLab 内置的安全模板(最方便)
include:
- template: Security/SAST.gitlab-ci.yml
- template: Security/Secret-Detection.gitlab-ci.yml
- template: Security/Dependency-Scanning.gitlab-ci.yml
- template: Security/Container-Scanning.gitlab-ci.yml # 需要容器镜像
- template: Security/DAST.gitlab-ci.yml # 需要部署环境
# 自定义 Trivy 扫描(如果需要更细致的控制)
container-scanning:
stage: security-scan
image: docker:latest
variables:
DOCKER_IMAGE: $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
script:
- docker run --rm -v /var/run/docker.sock:/var/run/docker.sock
aquasec/trivy image --exit-code 1 --severity CRITICAL $DOCKER_IMAGE
方案3:在 Jenkins 中集成(手动灵活配置)
pipeline {
agent any
stages {
stage('Checkout') { steps { checkout scm } }
stage('Build') {
steps {
sh 'npm install'
}
}
stage('SCA - Trivy') {
steps {
sh '''
trivy fs --exit-code 1 --severity CRITICAL .
'''
}
}
stage('SAST - SonarQube') {
steps {
withSonarQubeEnv('SonarQube') {
sh '''
sonar-scanner \
-Dsonar.projectKey=my-app \
-Dsonar.sources=. \
-Dsonar.host.url=$SONAR_HOST_URL \
-Dsonar.login=$SONAR_AUTH_TOKEN
'''
}
}
}
stage('Container Scan') {
when { branch 'main' }
steps {
sh 'trivy image --exit-code 1 myalatest'
}
}
}
post {
always {
// 发布 HTML 报告
publishHTML(target: [reportName: 'Trivy Report', reportDir: '.', reportFiles: 'report.html'])
}
}
}
最佳实践与注意事项
-
不要阻塞所有流水线:
对于Low或Info级别的告警,可以仅记录而不中断流水线,否则开发效率会大大降低。# 示例:仅在高危时中断,其他等级仅警告 trivy fs --exit-code 1 --severity CRITICAL . # 只阻断 Critical trivy fs --exit-code 0 --severity HIGH . # High 不阻断,但会报告
-
使用
SARIF格式:
这是一种标准化的漏洞报告格式,GitHub、GitLab、Azure DevOps等平台均原生支持解析SARIF文件,可以在PR中直接显示告警行号。 -
缓存扫描数据:
为了加快流水线速度,建议缓存Trivy、Snyk的漏洞数据库和SonarQube的扫描结果。# GitHub Actions 缓存示例 - name: Cache Trivy uses: actions/cache@v3 with: path: ~/.cache/trivy key: ${{ runner.os }}-trivy-${{ hashFiles('**/package-lock.json') }} -
优先集成SCA和密钥扫描:
这两类扫描发现的问题最实在(直接对应已知CVE或泄露的Token),且误报率较低。 -
避免镜像层扫描:
如果使用Trivy扫描容器镜像,建议先构建镜像,再扫描image,而不是扫描Dockerfile或构建步骤本身。
总结建议
- 初创团队/小项目:使用 Trivy + Gitleaks(全都在CLI中运行,无需额外服务)。
- 企业级/合规需求:采用 SonarQube (SAST) + Snyk (SCA) + Checkov (IaC) + GitGuardian (密钥),并结合OSS许可合规扫描。
- 云原生/容器化项目:在流水线中强制要求容器镜像签名的同时进行扫描,阻断漏洞镜像推送至生产仓库。
如果你能告诉我你使用的是哪种CI工具(如GitLab、Jenkins、CircleCI)以及主要的技术栈(Java/Go/Python等),我可以提供更具体的代码片段。