关于 implementing-devsecops-security-scanning
面向将自动化安全检查加入 CI/CD 流水线的团队,指导配置密钥检测、SAST、SCA 和 DAST,并汇总结果设置安全门禁及开发者反馈流程。
主要功能
- 01使用 Gitleaks 检测密钥
- 02使用 Semgrep 静态分析
- 03使用 Trivy 扫描依赖与容器
- 04使用 OWASP ZAP 扫描预发布环境
- 05汇总结果并设置安全门禁
- 06配置提交前开发者检查
适用场景
- 01将安全扫描加入 CI/CD
- 02根据高危发现阻止合并
- 03为构建生成 SBOM
- 04在推送代码前发现密钥
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ mukul975/ anthropic-cybersecurity-skills --skill implementing-devsecops-security-scanning安装后在 Claude Code 中输入/implementing-devsecops-security-scanning确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
LICENSEreferences/api-reference.mdscripts/agent.py详细介绍
实施 DevSecOps 安全扫描
何时使用
- 在新的或现有的 CI/CD 流水线中设置自动化安全扫描
- 将安全左移,在代码进入生产环境之前捕获漏洞
- 满足要求自动化安全测试的合规性要求(SOC 2、PCI-DSS、ISO 27001)
- 将 SAST、DAST 和 SCA 集成在一起,实现全面的应用安全覆盖
- 建立安全门禁,阻止包含严重或高危漏洞的部署
不要使用本指南替代手动渗透测试。自动化扫描能捕获常见的漏洞模式,但无法替代由人工驱动的安全评估,以发现业务逻辑缺陷和复杂攻击链。
前置条件
- CI/CD 平台:GitHub Actions、GitLab CI、Jenkins 或 Azure DevOps
- 用于运行扫描工具的容器运行时(Docker)
- 用于 DAST 扫描的预发布环境 URL(DAST 无法测试静态代码)
- 具有修改 CI/CD 工作流文件权限的仓库访问权限
- 工具特定要求:
- Semgrep:开源规则集(
p/security-audit、p/owasp-top-ten)免费 - Trivy:免费,无需账户
- OWASP ZAP:免费,提供 Docker 镜像
- Gitleaks:免费,无需账户
- Semgrep:开源规则集(
工作流
第 1 步:使用 Gitleaks 添加密钥检测
密钥检测最先运行,因为泄露的凭据是最高优先级的发现项。添加到 .github/workflows/security.yml:
name: DevSecOps Security Pipeline
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
jobs:
secrets-scan:
name: Secrets Detection (Gitleaks)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # Full history for scanning all commits
- name: Run Gitleaks
uses: gitleaks/gitleaks-action@v2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
在仓库根目录配置 .gitleaks.toml 以定义自定义规则和允许列表:
[extend]
useDefault = true
[allowlist]
description = "Global allowlist"
paths = [
'''\.gitleaks\.toml''',
'''test/fixtures/.*''',
'''docs/examples/.*'''
]
[[rules]]
id = "custom-internal-api-key"
description = "Internal API key pattern"
regex = '''INTERNAL_KEY_[A-Za-z0-9]{32}'''
tags = ["internal", "api-key"]
第 2 步:使用 Semgrep 添加 SAST 扫描
Semgrep 执行静态代码分析,以发现安全漏洞、缺陷和代码模式:
sast-scan:
name: SAST (Semgrep)
runs-on: ubuntu-latest
container:
image: semgrep/semgrep
steps:
- uses: actions/checkout@v4
- name: Run Semgrep SAST scan
run: |
semgrep scan \
--config p/security-audit \
--config p/owasp-top-ten \
--config p/secrets \
--severity ERROR \
--error \
--json \
--output semgrep-results.json \
.
- name: Upload SAST results
if: always()
uses: actions/upload-artifact@v4
with:
name: semgrep-results
path: semgrep-results.json
如需自定义规则,请创建 .semgrep/custom-rules.yml:
rules:
- id: no-exec-user-input
patterns:
- pattern: exec($INPUT)
- pattern-not: exec("...")
message: >
User input passed to exec(). This is a command injection vulnerability.
severity: ERROR
languages: [python]
metadata:
cwe: "CWE-78: OS Command Injection"
owasp: "A03:2021 - Injection"
- id: no-raw-sql-queries
patterns:
- pattern: cursor.execute(f"...")
- pattern: cursor.execute("..." + ...)
message: >
SQL query built with string concatenation or f-strings. Use parameterized queries.
severity: ERROR
languages: [python]
metadata:
cwe: "CWE-89: SQL Injection"
owasp: "A03:2021 - Injection"
第 3 步:使用 Trivy 添加 SCA 扫描
Trivy 扫描依赖项、容器镜像、IaC 文件,并生成 SBOM:
sca-scan:
name: SCA & Container Scan (Trivy)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run Trivy filesystem scan (dependencies)
uses: aquasecurity/[email protected]
with:
scan-type: 'fs'
scan-ref: '.'
severity: 'CRITICAL,HIGH'
exit-code: '1'
format: 'json'
output: 'trivy-fs-results.json'
- name: Run Trivy IaC scan (Terraform, CloudFormation)
uses: aquasecurity/[email protected]
with:
scan-type: 'config'
scan-ref: '.'
severity: 'CRITICAL,HIGH'
exit-code: '1'
format: 'json'
output: 'trivy-iac-results.json'
- name: Upload SCA results
if: always()
uses: actions/upload-artifact@v4
with:
name: trivy-results
path: trivy-*.json
container-scan:
name: Container Image Scan (Trivy)
runs-on: ubuntu-latest
needs: [sast-scan] # Build image only after SAST passes
steps:
- uses: actions/checkout@v4
- name: Build Docker image
run: docker build -t app:${{ github.sha }} .
- name: Scan container image
uses: aquasecurity/[email protected]
with:
image-ref: 'app:${{ github.sha }}'
severity: 'CRITICAL,HIGH'
exit-code: '1'
format: 'json'
output: 'trivy-image-results.json'
- name: Generate SBOM
uses: aquasecurity/[email protected]
with:
image-ref: 'app:${{ github.sha }}'
format: 'cyclonedx'
output: 'sbom.json'
- name: Upload SBOM
uses: actions/upload-artifact@v4
with:
name: sbom
path: sbom.json
第 4 步:使用 OWASP ZAP 添加 DAST 扫描
DAST 针对已部署的预发布环境运行。它比 SAST/SCA 更慢,应异步运行或按计划运行:
dast-scan:
name: DAST (OWASP ZAP)
runs-on: ubuntu-latest
needs: [deploy-staging] # Must run after app is deployed to staging
steps:
- uses: actions/checkout@v4
- name: Run ZAP Baseline Scan (fast, suitable for CI)
uses: zaproxy/[email protected]
with:
target: ${{ vars.STAGING_URL }}
rules_file_name: '.zap/rules.tsv'
cmd_options: '-a -j'
# For nightly full scans, use action-full-scan instead:
# - name: Run ZAP Full Scan (comprehensive, 30-60 min)
# uses: zaproxy/[email protected]
# with:
# target: ${{ vars.STAGING_URL }}
创建 .zap/rules.tsv 以配置告警阈值:
10010 IGNORE (Cookie No HttpOnly Flag - acceptable for non-sensitive cookies)
10011 IGNORE (Cookie Without Secure Flag - staging uses HTTP)
90033 WARN (Loosely Scoped Cookie)
10038 FAIL (Content Security Policy Header Not Set)
40012 FAIL (Cross Site Scripting - Reflected)
40014 FAIL (Cross Site Scripting - Persistent)
40018 FAIL (SQL Injection)
90019 FAIL (Server Side Code Injection)
90020 FAIL (Remote OS Command Injection)
第 5 步:汇总结果并强制执行安全门禁
创建一个汇总作业,聚合所有扫描结果并强制执行通过/失败门禁:
security-gate:
name: Security Gate
runs-on: ubuntu-latest
needs: [secrets-scan, sast-scan, sca-scan, container-scan]
if: always()
steps:
- name: Check scan results
run: |
echo "Checking security scan results..."
# Fail the pipeline if any upstream job failed
if [[ "${{ needs.secrets-scan.result }}" == "failure" ]]; then
echo "BLOCKED: Secrets detected in repository"
exit 1
fi
if [[ "${{ needs.sast-scan.result }}" == "failure" ]]; then
echo "BLOCKED: SAST found critical/high vulnerabilities"
exit 1
fi
if [[ "${{ needs.sca-scan.result }}" == "failure" ]]; then
echo "BLOCKED: SCA found critical/high vulnerable dependencies"
exit 1
fi
if [[ "${{ needs.container-scan.result }}" == "failure" ]]; then
echo "BLOCKED: Container image has critical/high vulnerabilities"
exit 1
fi
echo "All security gates passed"
第 6 步:配置分支保护规则
将安全流水线强制设为必需的状态检查:
GitHub Repository > Settings > Branches > Branch Protection Rules
Branch name pattern: main
Require status checks to pass before merging: Enabled
Required status checks:
- Secrets Detection (Gitleaks)
- SAST (Semgrep)
- SCA & Container Scan (Trivy)
- Security Gate
Require branches to be up to date before merging: Enabled
第 7 步:建立开发者反馈循环
配置 pre-commit 钩子,使开发者在推送之前就能发现问题:
# .pre-commit-config.yaml
repos:
- repo: https://github.com/gitleaks/gitleaks
rev: v8.22.1
hooks:
- id: gitleaks
- repo: https://github.com/semgrep/semgrep
rev: v1.102.0
hooks:
- id: semgrep
args: ['--config', 'p/security-audit', '--config', 'p/owasp-top-ten', '--error']
安装并激活 pre-commit:
pip install pre-commit
pre-commit install
pre-commit run --all-files # Test against existing codebase
关键概念
| 术语 | 定义 |
|---|---|
| SAST(静态应用安全测试) | 在不执行源代码的情况下分析源代码以发现安全漏洞;运行速度快,能及早发现问题,但无法发现运行时缺陷 |
| DAST(动态应用安全测试) | 通过发送请求并分析响应来测试正在运行的应用程序;能发现运行时问题,但需要已部署的环境 |
| SCA(软件成分分析) | 根据漏洞数据库(NVD、GitHub Advisory)扫描项目依赖项,以发现存在已知漏洞的库 |
| SBOM(软件物料清单) | 应用程序中所有组件和依赖项的机器可读清单,用于漏洞跟踪和合规性 |
| 左移(Shift Left) | 一种安全实践,将安全测试在 SDLC 中前移,从部署后阶段移至 pre-commit 和 CI 阶段 |
| 安全门禁(Security Gate) | CI/CD 流水线中的一个检查点,如果安全扫描结果超过定义的严重性阈值,则阻止部署 |
| Pre-commit 钩子 | 本地 Git 钩子,在代码提交之前运行安全检查,提供最快的开发者反馈循环 |
验证
- Gitleaks 阻止包含硬编码密钥的提交和 PR(使用虚拟 API key 测试)
- 每次 PR 都会运行 Semgrep 扫描,并以注解或评论形式报告发现
- Trivy 文件系统扫描能检测到已知存在漏洞的依赖(通过添加一个存在漏洞的包进行测试)
- Trivy 容器扫描能针对构建出的 Docker 镜像成功运行
- 生成 SBOM 并以 CycloneDX 或 SPDX 格式存储为构建产物
- OWASP ZAP 基线扫描能针对预发布 URL 运行且不崩溃
- 当任何扫描发现严重/高危问题时,安全门禁任务会阻止合并到 main
- 分支保护规则强制要求在合并前通过必需的状态检查
- 预提交钩子能在推送前于本地捕获密钥和 SAST 发现
- 开发者文档说明如何解读扫描结果并修复常见发现
评论
支持 Markdown