GitLab教程(11): 安全扫描与漏洞管理
GitLab提供了完整的安全扫描功能,可以在CI/CD流程中自动检测代码漏洞。本文将介绍GitLab的各种安全扫描工具和漏洞管理方法。
安全扫描类型
# GitLab支持的安全扫描类型
1. SAST (Static Application Security Testing)
- 静态代码分析
- 检测代码中的安全漏洞
- 支持多种语言
2. DAST (Dynamic Application Security Testing)
- 动态应用测试
- 对运行中的应用进行扫描
- 检测运行时漏洞
3. Dependency Scanning
- 依赖项漏洞扫描
- 检测第三方库的已知漏洞
4. Container Scanning
- 容器镜像扫描
- 检测Docker镜像中的漏洞
5. Secret Detection
- 密钥泄露检测
- 检测代码中的敏感信息
6. License Compliance
- 许可证合规检查
- 检测依赖项的许可证类型
启用安全扫描
# 使用GitLab模板快速启用所有扫描
include:
- template: Security/SAST.gitlab-ci.yml
- template: Security/Dependency-Scanning.gitlab-ci.yml
- template: Security/Secret-Detection.gitlab-ci.yml
- template: Security/Container-Scanning.gitlab-ci.yml
- template: Security/License-Scanning.gitlab-ci.yml
stages:
- build
- test
- security
# 所有扫描Job将自动添加到security阶段
SAST - 静态代码分析
# 启用SAST
include:
- template: Security/SAST.gitlab-ci.yml
# 支持的语言和工具
# - JavaScript/TypeScript: Semgrep, NodeJsScan
# - Python: Semgrep, Bandit
# - Java: Semgrep, SpotBugs
# - Go: Semgrep, Gosec
# - Ruby: Brakeman
# - PHP: PHPStan
# - C/C++: Flawfinder
# - .NET: Security Code Scan
# 自定义SAST配置
variables:
SAST_EXCLUDED_PATHS: "spec, test, tests, tmp"
SAST_EXCLUDED_ANALYZERS: "gosec, flawfinder"
SEARCH_MAX_DEPTH: 4
# SAST扫描输出
$ Running SAST analyzers
[INFO] Running Semgrep analyzer...
[INFO] Found 3 vulnerabilities
Vulnerability Report:
┌────────┬──────────────────────────────────┬──────────┬────────────┐
│ ID │ Description │ Severity │ File │
├────────┼──────────────────────────────────┼──────────┼────────────┤
│ SQL-01 │ SQL Injection vulnerability │ Critical │ db/user.js │
│ XSS-02 │ Cross-site scripting (XSS) │ High │ view/index │
│ SEC-03 │ Hardcoded credentials │ Medium │ config.js │
└────────┴──────────────────────────────────┴──────────┴────────────┘
Dependency Scanning
# 启用依赖扫描
include:
- template: Security/Dependency-Scanning.gitlab-ci.yml
# 支持的包管理器
# - npm/yarn (JavaScript)
# - pip/pipenv/poetry (Python)
# - Maven/Gradle (Java)
# - Go modules
# - Bundler (Ruby)
# - Composer (PHP)
# - NuGet (.NET)
# - Conan (C++)
# 配置变量
variables:
DS_EXCLUDED_PATHS: "spec, test, tests"
DS_EXCLUDED_ANALYZERS: "gemnasium-python"
# 扫描输出示例
$ Running dependency scanning...
[INFO] Analyzing package-lock.json
[INFO] Found 5 vulnerable dependencies
Vulnerable Dependencies:
┌────────────────────┬─────────────┬──────────┬────────────────┐
│ Package │ Version │ Severity │ Fixed Version │
├────────────────────┼─────────────┼──────────┼────────────────┤
│ lodash │ 4.17.15 │ Critical │ 4.17.21 │
│ axios │ 0.21.0 │ High │ 0.21.2 │
│ express │ 4.17.1 │ Medium │ 4.18.2 │
│ minimist │ 1.2.5 │ Medium │ 1.2.6 │
│ moment │ 2.29.1 │ Low │ 2.29.4 │
└────────────────────┴─────────────┴──────────┴────────────────┘
Secret Detection
# 启用密钥检测
include:
- template: Security/Secret-Detection.gitlab-ci.yml
# 检测的密钥类型
# - AWS Access Keys
# - Azure Service Principals
# - GCP Service Account Keys
# - GitHub Personal Access Tokens
# - GitLab Personal Access Tokens
# - Slack Tokens
# - SSH Private Keys
# - Database Passwords
# - API Keys
# 配置
variables:
SECRET_DETECTION_EXCLUDED_PATHS: "tests/fixtures"
SECRET_DETECTION_HISTORIC_SCAN: "true" # 扫描历史提交
# 扫描输出
$ Running secret detection...
[INFO] Scanning current commit...
[ALERT] Found 2 secrets
Secrets Found:
┌──────────────────────────┬────────────────────┬──────────┐
│ Type │ File │ Line │
├──────────────────────────┼────────────────────┼──────────┤
│ AWS Access Key │ config/aws.js │ 15 │
│ GitHub Personal Token │ scripts/deploy.sh │ 8 │
└──────────────────────────┴────────────────────┴──────────┘
[WARNING] Secrets should not be committed to the repository!
Use environment variables or a secrets manager.
Container Scanning
# 启用容器扫描
include:
- template: Security/Container-Scanning.gitlab-ci.yml
variables:
CS_IMAGE: $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
CS_SEVERITY_THRESHOLD: HIGH # 只报告HIGH和CRITICAL
# 需要先构建并推送镜像
stages:
- build
- scan
build:
stage: build
script:
- docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA .
- docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
container_scanning:
stage: scan
variables:
CS_IMAGE: $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
# 使用Trivy替代默认扫描器
container_scanning:
image:
name: aquasec/trivy:latest
entrypoint: [""]
script:
- trivy image --format json --output trivy-report.json $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
- trivy image --exit-code 1 --severity CRITICAL $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
artifacts:
reports:
container_scanning: trivy-report.json
allow_failure: true
# 扫描输出
$ trivy image registry.gitlab.com/mygroup/myproject:abc123
registry.gitlab.com/mygroup/myproject:abc123 (alpine 3.18)
Total: 12 (CRITICAL: 2, HIGH: 3, MEDIUM: 5, LOW: 2)
┌──────────────┬────────────────┬──────────┬────────────────┐
│ Library │ Vulnerability │ Severity │ Fixed Version │
├──────────────┼────────────────┼──────────┼────────────────┤
│ openssl │ CVE-2024-1234 │ CRITICAL │ 3.1.5-r0 │
│ libcurl │ CVE-2024-2345 │ CRITICAL │ 8.5.0-r0 │
│ busybox │ CVE-2024-3456 │ HIGH │ 1.36.1-r7 │
└──────────────┴────────────────┴──────────┴────────────────┘
DAST - 动态应用测试
# 启用DAST
include:
- template: DAST.gitlab-ci.yml
variables:
DAST_WEBSITE: https://staging.example.com
DAST_FULL_SCAN_ENABLED: "true"
# 需要先部署应用
stages:
- deploy
- dast
deploy-staging:
stage: deploy
script:
- ./deploy.sh staging
environment:
name: staging
url: https://staging.example.com
dast:
stage: dast
needs: [deploy-staging]
variables:
DAST_WEBSITE: https://staging.example.com
# DAST检测的漏洞类型
# - SQL Injection
# - Cross-Site Scripting (XSS)
# - Cross-Site Request Forgery (CSRF)
# - Insecure Headers
# - SSL/TLS Issues
# - Authentication Issues
# - Session Management Issues
# 使用OWASP ZAP进行扫描
dast:
image:
name: owasp/zap2docker-stable
entrypoint: [""]
script:
- zap-baseline.py -t https://staging.example.com -r zap-report.html
artifacts:
paths:
- zap-report.html
allow_failure: true
漏洞报告
# 查看漏洞报告
# Project > Security & Compliance > Vulnerability Report
# 漏洞仪表盘显示
┌─────────────────────────────────────────────────────────────┐
│ Vulnerability Report │
├─────────────────────────────────────────────────────────────┤
│ Total: 23 │
│ ├── Critical: 2 (需要立即处理) │
│ ├── High: 5 │
│ ├── Medium: 10 │
│ ├── Low: 6 │
│ └── Unknown: 0 │
│ │
│ By Scanner: │
│ ├── SAST: 8 │
│ ├── Dependency Scanning: 12 │
│ ├── Container Scanning: 3 │
│ └── Secret Detection: 0 │
└─────────────────────────────────────────────────────────────┘
# 漏洞状态
# - Detected: 新发现
# - Confirmed: 已确认
# - Dismissed: 已忽略(误报或不适用)
# - Resolved: 已修复
在MR中显示安全报告
# MR会自动显示新增的安全问题
# MR安全报告显示
┌─────────────────────────────────────────────────────────────┐
│ Security scanning detected 2 new potential vulnerabilities │
├─────────────────────────────────────────────────────────────┤
│ │
│ SAST │
│ ├── ⚠ SQL Injection in db/queries.js:45 │
│ │ Severity: Critical │
│ │ [Show details] [Dismiss] [Create issue] │
│ │ │
│ └── ⚠ Hardcoded password in config/db.js:12 │
│ Severity: High │
│ [Show details] [Dismiss] [Create issue] │
│ │
│ Dependency Scanning │
│ └── No new vulnerabilities │
│ │
└─────────────────────────────────────────────────────────────┘
# 配置MR安全检查
# Project > Settings > Merge requests
# Security approvals: 勾选需要安全批准
安全策略
# 配置安全策略 (需要Ultimate版)
# Group/Project > Security & Compliance > Policies
# 扫描执行策略示例
# .gitlab/security-policies/policy.yml
name: Required Security Scans
description: Enforce security scanning on all MRs
enabled: true
rules:
- type: pipeline
branches:
- main
- develop
actions:
- scan: sast
- scan: dependency_scanning
- scan: secret_detection
# 扫描结果策略
name: Block Critical Vulnerabilities
description: Block MR merge if critical vulnerabilities found
enabled: true
rules:
- type: scan_finding
scanners:
- sast
- dependency_scanning
vulnerabilities_allowed: 0
severity_levels:
- critical
vulnerability_states:
- detected
actions:
- type: require_approval
approvals_required: 1
user_approvers:
- security-team
修复建议
# 自动修复依赖漏洞
# MR页面 > Security > Dependency Scanning
# 点击 "Create merge request to remediate"
# 自动生成的MR会更新有漏洞的依赖版本
# 手动修复示例
# 1. SQL注入修复
# 修复前
const query = `SELECT * FROM users WHERE id = ${userId}`;
# 修复后 (使用参数化查询)
const query = 'SELECT * FROM users WHERE id = ?';
db.query(query, [userId]);
# 2. 依赖更新
npm audit fix
# 或
npm update lodash@4.17.21
# 3. 移除硬编码密钥
# 修复前
const apiKey = 'sk-1234567890abcdef';
# 修复后 (使用环境变量)
const apiKey = process.env.API_KEY;
完整配置示例
# 完整的安全扫描配置
include:
- template: Security/SAST.gitlab-ci.yml
- template: Security/Dependency-Scanning.gitlab-ci.yml
- template: Security/Secret-Detection.gitlab-ci.yml
- template: Security/Container-Scanning.gitlab-ci.yml
stages:
- build
- test
- security
- deploy
variables:
SAST_EXCLUDED_PATHS: "tests, spec, node_modules"
DS_EXCLUDED_PATHS: "tests"
CS_IMAGE: $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
SECRET_DETECTION_HISTORIC_SCAN: "false"
build:
stage: build
image: docker:24
services:
- docker:24-dind
script:
- docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA .
- docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
test:
stage: test
script:
- npm ci
- npm test
# 安全扫描Job由include自动添加
# 阻止部署如果有Critical漏洞
security-gate:
stage: security
needs: [sast, dependency_scanning, secret_detection, container_scanning]
script:
- echo "Checking security scan results..."
- |
if [ -f gl-sast-report.json ]; then
CRITICAL=$(jq '.vulnerabilities | map(select(.severity=="Critical")) | length' gl-sast-report.json)
if [ "$CRITICAL" -gt 0 ]; then
echo "Found $CRITICAL critical vulnerabilities! Blocking deployment."
exit 1
fi
fi
- echo "Security gate passed!"
allow_failure: false
deploy:
stage: deploy
needs: [security-gate]
script:
- ./deploy.sh
rules:
- if: $CI_COMMIT_BRANCH == "main"
总结
本文介绍了GitLab的安全扫描功能,包括SAST、依赖扫描、密钥检测和容器扫描。将安全扫描集成到CI/CD流程中可以尽早发现和修复安全问题。
下一篇我们将学习GitLab Pages静态网站托管。
声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。







