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