.zap/README.md
OWASP ZAP scans the running staging deployment for runtime vulnerabilities (injection,
XSS, header/TLS misconfig, exposed surfaces, auth gaps). It complements the static container
scan (Grype, .github/actions/sbom/).
.github/workflows/dast.ymldast-plan.yaml (ZAP Automation Framework)https://stg.activepieces.com with a dedicated throwaway account and obtains a
USER JWT.ghcr.io/zaproxy/zaproxy:stable image, injecting
Authorization: Bearer <jwt> on every request through a global replacer rule./api/v1/docs), spiders the
SPA + API (traditional + AJAX), then runs a full active injection scan.Runs nightly at 03:00 UTC (inside the staging deploy freeze window, so no deploy races the
scan) and on demand via workflow_dispatch. Non-blocking for now — findings are surfaced,
the build is never failed.
Active scanning sends real attack payloads. Two things keep the damage contained:
USER-scoped JWT — authorization limits any created/modified/deleted data to the throwaway account's own project.
excludePaths in dast-plan.yaml — a safety denylist for endpoints whose side effects
reach other people or external services, excluded even under full-active:
/api/v1/otp, /api/v1/authn/local — password-reset / verification emails/api/v1/user-invitations — invitation emails/api/v1/stripe-billing — payment provider webhook/ingest — PostHog reverse-proxy (open passthrough)/api/v1/admin — platform-admin surface (separate admin secret; unreachable with a USER JWT)To scan these anyway, remove the corresponding line — but understand the side effect first.
DAST_STG_EMAIL and DAST_STG_PASSWORD for that account.Add alertFilter entries in dast-plan.yaml (by ZAP ruleId) to downgrade or hide known
non-issues as the findings baseline is triaged.