Skip to content

ZAP DAST Scanner

Run ZAP (Zed Attack Proxy) DAST scanning and generate reports

uses: huntridge-labs/argus/.github/actions/scanner-zap@0.6.7

Dynamic Application Security Testing (DAST) using ZAP (Zed Attack Proxy).

Overview

This composite action runs ZAP to scan running web applications for security vulnerabilities. It supports:

  • Scan modes: url, docker-run, compose
  • Scan types: baseline, full, api
  • Dynamic artifact naming with hashed inputs
  • Optional PR comments and summary artifacts

Usage

URL Mode (Baseline)

- uses: huntridge-labs/argus/.github/actions/scanner-zap@0.6.7
  env:
    GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
  with:
    scan_type: baseline
    target_url: 'http://localhost:8080'
    fail_on_severity: 'high'

Docker-Run Mode (Image)

- uses: huntridge-labs/argus/.github/actions/scanner-zap@0.6.7
  env:
    GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
  with:
    scan_mode: docker-run
    scan_type: full
    app_image_ref: ghcr.io/acme/app:latest
    app_ports: '8080:8080'
    target_url: 'http://127.0.0.1:8080'
    registry_username: ${{ secrets.REGISTRY_USER }}
    registry_password: ${{ secrets.REGISTRY_TOKEN }}

Docker-Run Mode (Local Build)

- uses: huntridge-labs/argus/.github/actions/scanner-zap@0.6.7
  env:
    GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
  with:
    scan_mode: docker-run
    scan_type: baseline
    app_build_context: .
    app_dockerfile: Dockerfile
    app_image_tag: local-app:${{ github.sha }}
    app_ports: '8080:8080'
    target_url: 'http://127.0.0.1:8080'

Compose Mode

- uses: huntridge-labs/argus/.github/actions/scanner-zap@0.6.7
  env:
    GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
  with:
    scan_mode: compose
    scan_type: baseline
    compose_file: docker-compose.yml
    compose_build: 'true'
    target_url: 'http://127.0.0.1:8080'

API Scan

- uses: huntridge-labs/argus/.github/actions/scanner-zap@0.6.7
  env:
    GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
  with:
    scan_type: api
    api_spec: 'http://127.0.0.1:8080/openapi.json'
    fail_on_severity: 'medium'

Multi-Target Matrix

jobs:
  zap-scan:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        target:
          - { url: 'http://localhost:8080', name: 'web', type: 'baseline' }
          - { url: 'http://localhost:3000', name: 'api', type: 'full' }
    steps:
      - uses: actions/checkout@v6
      - uses: huntridge-labs/argus/.github/actions/scanner-zap@0.6.7
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          target_url: ${{ matrix.target.url }}
          scan_name: ${{ matrix.target.name }}
          scan_type: ${{ matrix.target.type }}

Config-Driven Multi-Scan

jobs:
  parse-zap:
    runs-on: ubuntu-latest
    outputs:
      matrix: ${{ steps.parse.outputs.matrix }}
      has_scans: ${{ steps.parse.outputs.has_scans }}
    steps:
      - uses: actions/checkout@v6
      - uses: huntridge-labs/argus/.github/actions/parse-zap-config@0.6.7
        id: parse
        with:
          config_file: .zap/config.yml

  zap-scan:
    runs-on: ubuntu-latest
    needs: parse-zap
    if: needs.parse-zap.outputs.has_scans == 'true'
    strategy:
      matrix: ${{ fromJson(needs.parse-zap.outputs.matrix) }}
    steps:
      - uses: actions/checkout@v6
      - uses: huntridge-labs/argus/.github/actions/scanner-zap@0.6.7
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          scan_name: ${{ matrix.name }}
          scan_mode: ${{ matrix.mode }}
          scan_type: ${{ matrix.scan_type }}
          target_url: ${{ matrix.target_url }}
          api_spec: ${{ matrix.api_spec }}
          app_image_ref: ${{ matrix.image }}
          app_ports: ${{ matrix.ports }}
          app_build_context: ${{ matrix.build_context }}
          app_dockerfile: ${{ matrix.build_dockerfile }}
          app_image_tag: ${{ matrix.build_tag }}
          compose_file: ${{ matrix.compose_file }}
          compose_build: ${{ matrix.compose_build }}
          registry_username: ${{ matrix.registry_username }}
          registry_password: ${{ secrets[matrix.registry_auth_secret] }}
          healthcheck_url: ${{ matrix.healthcheck_url }}
          max_duration_minutes: ${{ matrix.max_duration_minutes }}
          rules_file_name: ${{ matrix.rules_file }}
          cmd_options: ${{ matrix.cmd_options }}
          fail_on_severity: ${{ matrix.fail_on_severity }}
          allow_failure: ${{ matrix.allow_failure }}
          post_pr_comment: ${{ matrix.post_pr_comment }}

# IMPORTANT: When using secret references in the config, use `secrets: inherit` in the caller workflow.

Shared target tip: If you want multiple scans against a single started target (for example, one docker-run or compose stack), start the target once in a separate job and run scans with scan_mode: url against the shared target_url.

Inputs

Input Description Required Default
scan_name Unique scan identifier (for artifacts) No zap-scan
scan_mode url, docker-run, compose No url
scan_type baseline, full, api No baseline
target_url Target URL for baseline/full scans Conditionally ''
api_spec OpenAPI/Swagger spec URL (api scans) Conditionally ''
healthcheck_url URL to poll until target ready No ''
app_image_ref Container image for docker-run Conditionally ''
app_build_context Docker build context No ''
app_dockerfile Dockerfile path No ''
app_image_tag Tag for locally built image No ''
app_ports Port mappings (e.g., 8080:8080) No 8080:8080
compose_file Docker compose file path No docker-compose.yml
compose_build Run docker compose with --build No true
registry_username Registry username (private images) No ''
registry_password Registry password/token (private images) No ''
max_duration_minutes Max scan duration in minutes No 10
rules_file_name ZAP rules file to ignore alerts (.tsv) No ''
cmd_options Additional ZAP command-line options No ''
fail_on_severity none, low, medium, high, critical No none
allow_failure Continue on scan failure (true/false) No false
post_pr_comment Post results as PR comment (true/false) No false
job_id Job ID for artifact naming No ${{ github.job }}

Outputs

Output Description
findings_count Total number of findings (high+medium+low)
high_count Number of high severity findings
medium_count Number of medium severity findings
low_count Number of low severity findings
info_count Number of informational findings
scan_status passed, failed, or skipped

Reports Generated

The action generates multiple report formats (JSON/HTML/Markdown/SARIF) and uploads them as artifacts with a hashed prefix.

Notes on Secrets

Composite actions cannot access secrets directly. Pass secrets as inputs, for example:

with:
  registry_username: ${{ secrets.REGISTRY_USER }}
  registry_password: ${{ secrets.REGISTRY_TOKEN }}

Troubleshooting

  • Connection Refused: verify the target is running and reachable from the runner.
  • Compose file not found: ensure compose_file points to a file in the repo.
  • Timeout waiting for readiness: set healthcheck_url or increase startup time.