Skip to content

actions-scanner-zap-full-example.yml

name: ZAP DAST - Full Input Exercise

# Exercises every input on the current scanner-zap composite action.
# Earlier revisions of this example covered docker-build / docker-
# compose / api-spec / healthcheck-poll / max-duration / cmd-options
# flows — those inputs were removed from scanner-zap when the action
# was scoped down. Build / health-check / start logic that used to
# live inside the action now lives in workflow steps before the
# scanner runs (see the "Start <target>" steps below).
#
# scanner-zap's current input surface:
#   scan_name, scan_mode, scan_type, target_url,
#   app_image_ref, app_ports, app_env, startup_timeout,
#   fail_on_severity, post_pr_comment, enable_code_security,
#   job_id, python_version

on:
  workflow_dispatch:

permissions:
  contents: read
  actions: read
  pull-requests: write

jobs:
  zap-full-inputs:
    name: ZAP ${{ matrix.name }}
    runs-on: ubuntu-latest
    timeout-minutes: 60
    strategy:
      fail-fast: false
      matrix:
        include:
          # ------------------------------------------------------------
          # url mode — caller is responsible for the running target.
          # We start nginx via ``docker run`` in a previous step.
          # ------------------------------------------------------------
          - name: url-baseline
            scan_name: url-baseline
            scan_mode: url
            scan_type: baseline
            target_url: http://127.0.0.1:8080
            fail_on_severity: none
            post_pr_comment: 'false'

          # ------------------------------------------------------------
          # docker-run mode — scanner-zap brings up app_image_ref as
          # a sidecar on the configured ports. app_env is forwarded
          # into the container; startup_timeout caps the wait for the
          # container to become reachable.
          # ------------------------------------------------------------
          - name: docker-run-full-image
            scan_name: docker-run-full-image
            scan_mode: docker-run
            scan_type: full
            app_image_ref: nginx:alpine
            app_ports: '8081:80'
            app_env: ''
            startup_timeout: '60'
            target_url: http://127.0.0.1:8081
            fail_on_severity: none
            post_pr_comment: 'false'

          # ------------------------------------------------------------
          # api scan — scan_type=api with a target_url. The previous
          # api_spec input was removed; ZAP discovers endpoints from
          # the URL itself.
          # ------------------------------------------------------------
          - name: api-scan
            scan_name: api-scan
            scan_mode: url
            scan_type: api
            target_url: http://127.0.0.1:8084
            fail_on_severity: medium
            post_pr_comment: 'true'

    steps:
      - name: Checkout repository
        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6

      - name: Start URL target (manual)
        if: matrix.scan_mode == 'url' && matrix.scan_type != 'api'
        run: |
          docker run -d --rm --name zap-url-target -p 8080:80 nginx:alpine
          echo "URL_CONTAINER_NAME=zap-url-target" >> "$GITHUB_ENV"

      - name: Start API target
        if: matrix.scan_type == 'api'
        run: |
          # Trivial OpenAPI server — replace with your real API
          # under test. ZAP scan_type=api crawls from the target_url.
          mkdir -p zap-api
          cat > zap-api/openapi.json <<'EOF'
          {
            "openapi": "3.0.0",
            "info": { "title": "ZAP Sample API", "version": "1.0.0" },
            "paths": {
              "/health": {
                "get": {
                  "responses": { "200": { "description": "OK" } }
                }
              }
            }
          }
          EOF
          python -m http.server 8084 --directory zap-api >/tmp/zap-api.log 2>&1 &
          # Brief wait for the server to bind. scanner-zap doesn't
          # poll a healthcheck_url anymore; consumers handle readiness
          # before the action runs.
          sleep 2

      - name: Run ZAP scanner (current input set)
        uses: huntridge-labs/argus/.github/actions/scanner-zap@1.1.0
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          scan_name: ${{ matrix.scan_name }}
          scan_type: ${{ matrix.scan_type }}
          target_url: ${{ matrix.target_url || '' }}
          app_image_ref: ${{ matrix.app_image_ref || '' }}
          app_ports: ${{ matrix.app_ports || '' }}
          app_env: ${{ matrix.app_env || '' }}
          startup_timeout: ${{ matrix.startup_timeout || '60' }}
          fail_on_severity: ${{ matrix.fail_on_severity }}
          post_pr_comment: ${{ matrix.post_pr_comment }}

      - name: Stop URL target
        if: always() && env.URL_CONTAINER_NAME != ''
        run: |
          docker stop "$URL_CONTAINER_NAME" || true