integrating-dast-with-owasp-zap-in-pipeline

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Integrating DAST with OWASP ZAP in Pipeline

在流水线中集成OWASP ZAP实现DAST测试

When to Use

适用场景

  • When testing running web applications for vulnerabilities like XSS, SQLi, CSRF, and misconfigurations
  • When SAST alone is insufficient and runtime behavior testing is required
  • When compliance mandates dynamic security testing of web applications before production
  • When testing APIs (REST/GraphQL) for authentication, authorization, and injection flaws
  • When establishing continuous DAST scanning in staging environments before production deployment
Do not use for scanning source code (use SAST), for scanning dependencies (use SCA), or for infrastructure configuration scanning (use IaC scanning tools).
  • 针对运行中的Web应用测试XSS、SQL注入(SQLi)、CSRF及配置错误等漏洞时
  • 仅使用静态应用安全测试(SAST)不足以满足需求,需要测试运行时行为时
  • 合规要求在生产部署前对Web应用进行动态安全测试时
  • 针对REST/GraphQL API测试认证、授权及注入缺陷时
  • 在生产部署前,在预发布环境中建立持续DAST扫描机制时
不适用场景:扫描源代码(请使用SAST)、扫描依赖项(请使用SCA)或扫描基础设施配置(请使用IaC扫描工具)。

Prerequisites

前提条件

  • OWASP ZAP Docker image or installed locally (zaproxy/zap-stable or zaproxy/action-*)
  • Running target application accessible from the CI/CD runner (staging URL or Docker service)
  • ZAP scan rules configuration (optional, for tuning)
  • OpenAPI/Swagger specification for API scanning (optional)
  • OWASP ZAP Docker镜像或本地安装版本(zaproxy/zap-stable或zaproxy/action-*)
  • CI/CD运行器可访问的运行中目标应用(预发布URL或Docker服务)
  • ZAP扫描规则配置(可选,用于自定义扫描)
  • API扫描用的OpenAPI/Swagger规范(可选)

Workflow

工作流程

Step 1: Configure ZAP Baseline Scan in GitHub Actions

步骤1:在GitHub Actions中配置ZAP基线扫描

yaml
undefined
yaml
undefined

.github/workflows/dast-scan.yml

.github/workflows/dast-scan.yml

name: DAST Security Scan
on: deployment_status: workflow_dispatch: inputs: target_url: description: 'Target URL to scan' required: true
jobs: zap-baseline: name: ZAP Baseline Scan runs-on: ubuntu-latest services: webapp: image: ${{ github.repository }}:${{ github.sha }} ports: - 8080:8080 options: --health-cmd="curl -f http://localhost:8080/health" --health-interval=10s --health-timeout=5s --health-retries=5
steps:
  - uses: actions/checkout@v4

  - name: ZAP Baseline Scan
    uses: zaproxy/action-baseline@v0.12.0
    with:
      target: 'http://webapp:8080'
      rules_file_name: '.zap/rules.tsv'
      cmd_options: '-a -j'
      allow_issue_writing: false

  - name: Upload ZAP Report
    if: always()
    uses: actions/upload-artifact@v4
    with:
      name: zap-baseline-report
      path: report_html.html
undefined
name: DAST Security Scan
on: deployment_status: workflow_dispatch: inputs: target_url: description: 'Target URL to scan' required: true
jobs: zap-baseline: name: ZAP Baseline Scan runs-on: ubuntu-latest services: webapp: image: ${{ github.repository }}:${{ github.sha }} ports: - 8080:8080 options: --health-cmd="curl -f http://localhost:8080/health" --health-interval=10s --health-timeout=5s --health-retries=5
steps:
  - uses: actions/checkout@v4

  - name: ZAP Baseline Scan
    uses: zaproxy/action-baseline@v0.12.0
    with:
      target: 'http://webapp:8080'
      rules_file_name: '.zap/rules.tsv'
      cmd_options: '-a -j'
      allow_issue_writing: false

  - name: Upload ZAP Report
    if: always()
    uses: actions/upload-artifact@v4
    with:
      name: zap-baseline-report
      path: report_html.html
undefined

Step 2: Configure ZAP Full Scan for Comprehensive Testing

步骤2:配置ZAP全面扫描以开展深度测试

yaml
  zap-full-scan:
    name: ZAP Full Scan
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: ZAP Full Scan
        uses: zaproxy/action-full-scan@v0.12.0
        with:
          target: ${{ github.event.inputs.target_url || 'https://staging.example.com' }}
          rules_file_name: '.zap/rules.tsv'
          cmd_options: '-a -j -T 60'

      - name: Upload Reports
        if: always()
        uses: actions/upload-artifact@v4
        with:
          name: zap-full-report
          path: |
            report_html.html
            report_json.json
yaml
  zap-full-scan:
    name: ZAP Full Scan
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: ZAP Full Scan
        uses: zaproxy/action-full-scan@v0.12.0
        with:
          target: ${{ github.event.inputs.target_url || 'https://staging.example.com' }}
          rules_file_name: '.zap/rules.tsv'
          cmd_options: '-a -j -T 60'

      - name: Upload Reports
        if: always()
        uses: actions/upload-artifact@v4
        with:
          name: zap-full-report
          path: |
            report_html.html
            report_json.json

Step 3: Configure API Scan with OpenAPI Specification

步骤3:结合OpenAPI规范配置API扫描

yaml
  zap-api-scan:
    name: ZAP API Scan
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: ZAP API Scan
        uses: zaproxy/action-api-scan@v0.12.0
        with:
          target: 'https://staging.example.com/api/openapi.json'
          format: openapi
          rules_file_name: '.zap/api-rules.tsv'
          cmd_options: '-a -j'
yaml
  zap-api-scan:
    name: ZAP API Scan
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: ZAP API Scan
        uses: zaproxy/action-api-scan@v0.12.0
        with:
          target: 'https://staging.example.com/api/openapi.json'
          format: openapi
          rules_file_name: '.zap/api-rules.tsv'
          cmd_options: '-a -j'

Step 4: Configure ZAP Scan Rules

步骤4:配置ZAP扫描规则

tsv
undefined
tsv
undefined

.zap/rules.tsv

.zap/rules.tsv

Rule ID Action (IGNORE/WARN/FAIL) Description

Rule ID Action (IGNORE/WARN/FAIL) Description

10003 IGNORE # Vulnerable JS Library (handled by SCA) 10015 WARN # Incomplete or No Cache-control Header 10021 FAIL # X-Content-Type-Options Missing 10035 FAIL # Strict-Transport-Security Missing 10038 FAIL # Content Security Policy Missing 10098 IGNORE # Cross-Domain Misconfiguration (CDN) 40012 FAIL # Cross Site Scripting (Reflected) 40014 FAIL # Cross Site Scripting (Persistent) 40018 FAIL # SQL Injection 40019 FAIL # SQL Injection (MySQL) 40032 FAIL # .htaccess Information Leak 90033 FAIL # Loosely Scoped Cookie
undefined
10003 IGNORE # Vulnerable JS Library (handled by SCA) 10015 WARN # Incomplete or No Cache-control Header 10021 FAIL # X-Content-Type-Options Missing 10035 FAIL # Strict-Transport-Security Missing 10038 FAIL # Content Security Policy Missing 10098 IGNORE # Cross-Domain Misconfiguration (CDN) 40012 FAIL # Cross Site Scripting (Reflected) 40014 FAIL # Cross Site Scripting (Persistent) 40018 FAIL # SQL Injection 40019 FAIL # SQL Injection (MySQL) 40032 FAIL # .htaccess Information Leak 90033 FAIL # Loosely Scoped Cookie
undefined

Step 5: Run ZAP with Docker Compose for Local Testing

步骤5:使用Docker Compose运行ZAP进行本地测试

yaml
undefined
yaml
undefined

docker-compose.zap.yml

docker-compose.zap.yml

version: '3.8' services: webapp: build: . ports: - "8080:8080" healthcheck: test: ["CMD", "curl", "-f", "http://localhost:8080/health"] interval: 10s retries: 5
zap: image: zaproxy/zap-stable:latest depends_on: webapp: condition: service_healthy command: > zap-baseline.py -t http://webapp:8080 -r /zap/wrk/report.html -J /zap/wrk/report.json -c /zap/wrk/rules.tsv -I volumes: - ./zap-reports:/zap/wrk - ./.zap/rules.tsv:/zap/wrk/rules.tsv
undefined
version: '3.8' services: webapp: build: . ports: - "8080:8080" healthcheck: test: ["CMD", "curl", "-f", "http://localhost:8080/health"] interval: 10s retries: 5
zap: image: zaproxy/zap-stable:latest depends_on: webapp: condition: service_healthy command: > zap-baseline.py -t http://webapp:8080 -r /zap/wrk/report.html -J /zap/wrk/report.json -c /zap/wrk/rules.tsv -I volumes: - ./zap-reports:/zap/wrk - ./.zap/rules.tsv:/zap/wrk/rules.tsv
undefined

Key Concepts

核心概念

TermDefinition
DASTDynamic Application Security Testing — tests running applications by sending requests and analyzing responses
Baseline ScanQuick passive scan that spiders the application without active attacks, suitable for CI/CD
Full ScanActive scan including attack payloads for XSS, SQLi, and other injection vulnerabilities
API ScanTargeted scan using OpenAPI/Swagger specs to test all documented API endpoints
SpiderZAP's crawler that discovers application pages and endpoints by following links
Active ScanPhase where ZAP sends attack payloads to discovered endpoints to find exploitable vulnerabilities
Passive ScanAnalysis of HTTP responses for security headers, cookies, and information disclosure without sending attacks
Scan PolicyConfiguration defining which attack types to enable and their intensity levels
术语定义
DAST动态应用安全测试——通过发送请求并分析响应来测试运行中的应用
Baseline Scan快速被动扫描,会爬取应用但不发起主动攻击,适合CI/CD场景
Full Scan主动扫描,包含针对XSS、SQL注入及其他注入漏洞的攻击载荷
API Scan基于OpenAPI/Swagger规范的定向扫描,用于测试所有已文档化的API端点
SpiderZAP的爬虫工具,通过跟随链接发现应用页面和端点
Active ScanZAP向已发现的端点发送攻击载荷以查找可利用漏洞的阶段
Passive Scan分析HTTP响应中的安全头、Cookie和信息泄露情况,不发起攻击
Scan Policy定义启用哪些攻击类型及其强度级别的配置

Tools & Systems

工具与系统

  • OWASP ZAP: Open-source web application security scanner for DAST testing
  • zaproxy/action-baseline: GitHub Action for ZAP passive baseline scanning
  • zaproxy/action-full-scan: GitHub Action for ZAP active full scanning
  • zaproxy/action-api-scan: GitHub Action for API-focused scanning with OpenAPI support
  • Nuclei: Alternative vulnerability scanner with template-based detection for CI/CD integration
  • OWASP ZAP: 用于DAST测试的开源Web应用安全扫描器
  • zaproxy/action-baseline: 用于ZAP被动基线扫描的GitHub Action
  • zaproxy/action-full-scan: 用于ZAP主动全面扫描的GitHub Action
  • zaproxy/action-api-scan: 支持OpenAPI的API聚焦扫描GitHub Action
  • Nuclei: 基于模板检测的替代漏洞扫描器,适合CI/CD集成

Common Scenarios

常见场景

Scenario: Integrating DAST into a Staging Deployment Pipeline

场景:将DAST集成到预发布部署流水线

Context: A team deploys to staging before production and needs automated DAST scanning between stages to catch runtime vulnerabilities.
Approach:
  1. Add a DAST job in the pipeline that triggers after successful staging deployment
  2. Run ZAP baseline scan first for quick passive feedback (2-5 minutes)
  3. Follow with a targeted API scan using the application's OpenAPI specification
  4. Configure rules.tsv to FAIL on critical findings (XSS, SQLi) and WARN on headers/cookies
  5. Upload ZAP reports as pipeline artifacts for review
  6. Block production deployment if any FAIL-level findings are detected
  7. Schedule weekly full scans against staging for deeper coverage
Pitfalls: ZAP full scans can take 30+ minutes and may overwhelm staging servers with attack traffic. Use baseline scans in CI and full scans on schedule. Running DAST against production without coordination can trigger WAF blocks and incident alerts.
背景:团队在生产部署前会先部署到预发布环境,需要在阶段之间加入自动化DAST扫描以发现运行时漏洞。
实施方法
  1. 在流水线中添加DAST任务,成功部署到预发布环境后触发
  2. 先运行ZAP基线扫描以快速获得被动反馈(2-5分钟)
  3. 随后使用应用的OpenAPI规范进行定向API扫描
  4. 配置rules.tsv,将严重检测结果(如XSS、SQL注入)设为FAIL,将头信息/Cookie相关问题设为WARN
  5. 将ZAP报告上传为流水线工件以供审核
  6. 若存在任何FAIL级别的检测结果,阻止生产部署
  7. 每周针对预发布环境安排一次全面扫描以获得更深度的覆盖
注意事项:ZAP全面扫描可能需要30分钟以上,且攻击流量可能会压垮预发布服务器。建议在CI中使用基线扫描,全面扫描则按计划执行。未经协调直接在生产环境运行DAST可能会触发WAF拦截和事件告警。

Output Format

输出格式

ZAP DAST Scan Report
======================
Target: https://staging.example.com
Scan Type: Baseline + API
Date: 2026-02-23
Duration: 4m 32s

FINDINGS:
  FAIL: 3
  WARN: 7
  INFO: 12
  PASS: 45

FAILING ALERTS:
  [HIGH] 40012 - Cross Site Scripting (Reflected)
    URL: https://staging.example.com/search?q=<script>
    Method: GET
    Evidence: <script>alert(1)</script>

  [MEDIUM] 10021 - X-Content-Type-Options Missing
    URL: https://staging.example.com/api/v1/*
    Evidence: Response header missing

  [MEDIUM] 10035 - Strict-Transport-Security Missing
    URL: https://staging.example.com/
    Evidence: HSTS header not present

QUALITY GATE: FAILED (1 HIGH, 2 MEDIUM findings)
ZAP DAST Scan Report
======================
Target: https://staging.example.com
Scan Type: Baseline + API
Date: 2026-02-23
Duration: 4m 32s

FINDINGS:
  FAIL: 3
  WARN: 7
  INFO: 12
  PASS: 45

FAILING ALERTS:
  [HIGH] 40012 - Cross Site Scripting (Reflected)
    URL: https://staging.example.com/search?q=<script>
    Method: GET
    Evidence: <script>alert(1)</script>

  [MEDIUM] 10021 - X-Content-Type-Options Missing
    URL: https://staging.example.com/api/v1/*
    Evidence: Response header missing

  [MEDIUM] 10035 - Strict-Transport-Security Missing
    URL: https://staging.example.com/
    Evidence: HSTS header not present

QUALITY GATE: FAILED (1 HIGH, 2 MEDIUM findings)