【CI/CD·GitLab篇】安全扫描集成:SAST、DAST 与依赖扫描配置

发布时间:2026/8/9 2:22:09
【CI/CD·GitLab篇】安全扫描集成:SAST、DAST 与依赖扫描配置 前言安全左移Shift Left Security是 DevSecOps 的核心理念——把安全检查从生产环境移到 CI 阶段问题越早发现修复成本越低。本篇讲清楚 SAST、DAST、依赖扫描、容器扫描四种安全扫描的原理和 GitLab CI 集成方式。一、四种安全扫描对比| 类型 | 全称 | 扫描对象 | 扫描阶段 | 是否需要运行 ||------|------|---------|---------|-------------|| SAST | Static Application Security Testing | 源代码 | 编译后 | 否 || DAST | Dynamic Application Security Testing | 运行中的应用 | 部署后 | 是 || 依赖扫描 | Dependency Scanning | 第三方依赖 | 构建时 | 否 || 容器扫描 | Container Scanning | Docker 镜像 | 构建后 | 否 |开发流程中的安全检查点: 代码提交 → SAST扫描(源码) → 依赖扫描(依赖) → 构建镜像 → 容器扫描(镜像) → 部署 → DAST扫描(运行时) ↑ ↑ ↑ ↑ ↑ 左移最早 发现已知漏洞 镜像层漏洞 运行时漏洞二、SAST静态代码安全扫描原理不运行代码通过分析源代码的模式来发现安全漏洞SQL注入、XSS、硬编码密钥等。GitLab 内置 SAST# .gitlab-ci.yml include: - template: Security/SAST.gitlab-ci.yml sast: stage: test variables: SEARCH_MAX_DEPTH: 10 # 扫描目录深度 SAST_EXCLUDED_PATHS: spec,test,tests,bin,node_modules # 排除目录 rules: - if: $CI_PIPELINE_SOURCE merge_request_event - if: $CI_COMMIT_BRANCH main自定义 SASTSonarQubesonar-sast: stage: test image: name: sonarsource/sonar-scanner-cli:latest entrypoint: [] variables: SONAR_PROJECT_KEY: myapp SONAR_SOURCES: src script: - | sonar-scanner \ -Dsonar.projectKey$SONAR_PROJECT_KEY \ -Dsonar.projectNameMy Application \ -Dsonar.sources$SONAR_SOURCES \ -Dsonar.host.url$SONAR_HOST_URL \ -Dsonar.login$SONAR_TOKEN \ -Dsonar.qualitygate.waittrue # 等待质量门检查 artifacts: reports: sast: gl-sast-report.json rules: - if: $CI_PIPELINE_SOURCE merge_request_event - if: $CI_COMMIT_BRANCH mainSonarQube 质量门规则在 SonarQube → Quality Gates 中配置质量门名称: CI Gate 条件: - Coverage on New Code 70% → FAIL - Duplicated Lines on New Code 3% → FAIL - Bugs Rating 1 (A) on New Code → FAIL - Vulnerabilities Rating 1 (A) on New Code → FAIL - Security Hotspots Reviewed 100% → FAIL**培训要点**sonar.qualitygate.waittrue 会让 CI 等待质量门检查结果。如果质量门不过SonarQube 返回非零退出码CI Job 自动失败。这是安全门禁的核心机制。三、依赖扫描第三方漏洞检测原理扫描项目的依赖清单pom.xml、package.json、go.mod 等对照已知漏洞数据库CVE检查是否有受影响的依赖。GitLab 内置依赖扫描include: - template: Security/Dependency-Scanning.gitlab-ci.yml dependency_scanning: stage: test variables: DS_EXCLUDED_ANALYZERS: gemnasium-maven # 排除特定分析器 DS_EXCLUDED_PATHS: vendor,third_party # 排除目录 rules: - if: $CI_PIPELINE_SOURCE merge_request_event - if: $CI_COMMIT_BRANCH mainTrivy 依赖扫描dependency-scan: stage: test image: aquasec/trivy:latest needs: [build] script: # 扫描 Maven 依赖 - trivy fs --exit-code 1 --severity HIGH,CRITICAL ./target/ # 或直接扫描 pom.xml - trivy maven --exit-code 1 --severity HIGH,CRITICAL pom.xml artifacts: reports: dependency_scanning: gl-dependency-scanning-report.json rules: - if: $CI_PIPELINE_SOURCE merge_request_event - if: $CI_COMMIT_BRANCH main自动修复依赖漏洞Renovate# 在仓库中添加 .renovaterc.json { extends: [config:base], schedule: [before 6am on Monday], // 每周一早上6点前检查 labels: [dependencies], vulnerabilityAlerts: { enabled: true, labels: [security] }, packageRules: [ { matchUpdateTypes: [patch], automerge: true // 补丁版本自动合并 }, { matchUpdateTypes: [major], automerge: false // 大版本手动审查 } ] }**踩坑提示**不要把所有依赖升级都设为自动合并。Patch 级别如 1.2.3→1.2.4可以自动Minor1.2→1.3和 Major1→2必须手动测试。否则一次自动升级可能打破应用。四、容器镜像扫描Trivy 镜像扫描container-scan: stage: scan image: aquasec/trivy:latest needs: [package] services: - docker:24-dind variables: IMAGE: $REGISTRY/myapp:$CI_COMMIT_SHORT_SHA TRIVY_EXIT_CODE: 1 TRIVY_SEVERITY: HIGH,CRITICAL script: # 拉取镜像 - docker pull $IMAGE # 扫描漏洞 - trivy image --exit-code $TRIVY_EXIT_CODE --severity $TRIVY_SEVERITY \ --format json --output trivy-image-report.json \ --ignorefile .trivyignore \ $IMAGE # 扫描配置文件Dockerfile 最佳实践检查 - trivy config --severity HIGH,CRITICAL --format json --output trivy-config-report.json . artifacts: paths: - trivy-image-report.json - trivy-config-report.json reports: container_scanning: trivy-image-report.json rules: - if: $CI_COMMIT_BRANCH main.trivyignore 文件# .trivyignore — 忽略已知且暂不修复的漏洞 # 格式: CVE-ID CVE-2024-12345 # 暂不修复需等待上游修复 CVE-2024-67890 # 已评估风险可接受Grype 替代方案container-scan-grype: stage: scan image: anchore/grype:latest needs: [package] script: - grype $IMAGE --fail-on high --output json grype-report.json artifacts: paths: [grype-report.json]五、DAST动态安全扫描原理在应用运行时对其进行攻击测试——模拟 SQL注入、XSS、CSRF 等攻击。GitLab 内置 DASTinclude: - template: Security/DAST.gitlab-ci.yml dast: stage: dast needs: [deploy-test] variables: DAST_WEBSITE: https://test.myapp.com DAST_AUTH_URL: https://test.myapp.com/login DAST_USERNAME: testuser DAST_PASSWORD: $DAST_TEST_PASSWORD DAST_BROWSER: chrome # 使用 Chrome 浏览器扫描 DAST_FULL_SCAN_ENABLED: true # 完整扫描慢但全面 rules: - if: $CI_COMMIT_BRANCH mainOWASP ZAP 集成dast-zap: stage: dast needs: [deploy-test] image: name: owasp/zap2docker-stable entrypoint: [] variables: TARGET_URL: https://test.myapp.com script: # 基线扫描快速 - zap-baseline.py -t $TARGET_URL -c zap-baseline.conf -J zap-report.json # 完整扫描慢但全面适合定期执行 # - zap-full-scan.py -t $TARGET_URL -c zap-baseline.conf -J zap-report.json artifacts: paths: [zap-report.json] reports: dast: zap-report.json rules: - if: $CI_COMMIT_BRANCH main allow_failure: true # DAST 扫描不阻塞流水线ZAP 基线配置# zap-baseline.conf # 忽略的规则误报 zap.excludeRules 10010,10015,10020 # 阈值 zap.rulesToFail 40003,40012,40014 # 这些规则触发则失败六、安全报告整合GitLab Security Dashboard所有安全扫描的产物报告用reports字段提交GitLab 会自动整合到 Security Dashboardartifacts: reports: sast: gl-sast-report.json dependency_scanning: gl-dependency-scanning-report.json container_scanning: trivy-image-report.json dast: zap-report.json在 GitLab → Security Compliance → Security Dashboard 中可以看到按严重程度分类的漏洞列表按时间趋势的漏洞数量变化每个 MR 的安全差异对比安全门禁# 安全质量门HIGH/CRITICAL 漏洞阻止合并 security-gate: stage: scan needs: [sast, dependency-scan, container-scan] script: # 统计 HIGH 和 CRITICAL 漏洞数 - | CRITICAL_COUNT0 HIGH_COUNT0 for report in gl-sast-report.json gl-dependency-scanning-report.json trivy-image-report.json; do if [ -f $report ]; then CRITICAL$(jq [.vulnerabilities[]? | select(.severity Critical)] | length $report 2/dev/null || echo 0) HIGH$(jq [.vulnerabilities[]? | select(.severity High)] | length $report 2/dev/null || echo 0) CRITICAL_COUNT$((CRITICAL_COUNT CRITICAL)) HIGH_COUNT$((HIGH_COUNT HIGH)) fi done echo Critical vulnerabilities: $CRITICAL_COUNT echo High vulnerabilities: $HIGH_COUNT if [ $CRITICAL_COUNT -gt 0 ]; then echo BLOCKED: $CRITICAL_COUNT critical vulnerabilities found exit 1 fi rules: - if: $CI_PIPELINE_SOURCE merge_request_event七、本篇要点回顾1. 四种扫描SAST 扫源码、依赖扫描扫依赖、容器扫描扫镜像、DAST 扫运行时2. SAST 用 GitLab 内置或 SonarQube配质量门阻断有漏洞的代码3. 依赖扫描对照 CVE 数据库Patch 版本可自动升级Major 版本手动4. 容器扫描用 Trivy.trivyignore忽略已知风险5. DAST 在部署后扫描用allow_failure: true不阻塞流水线6. 所有报告用reports字段提交GitLab 自动整合到 Security Dashboard下一篇预告GitLab 篇结束接下来进入 GitHub Actions 篇《入门Workflow 语法与自托管 Runner》。