Raxx · internal docs

internal · gated ↑ index

ZAP Finding Triage — Operator Runbook

This runbook covers what to do when the OWASP ZAP baseline scan fires on a PR or weekly schedule run.

When does ZAP run?

Trigger Target Who sees it
PR opened/pushed (Antlers surface only) Branch preview URL on Cloudflare Pages PR comment posted automatically
Weekly schedule — Monday 09:07 UTC https://raxx-app.pages.dev + https://raxx-api-staging.herokuapp.com/ GitHub Actions step summary + auto-filed issues
Manual workflow_dispatch Override URL (staging only) Step summary

Run location: .github/workflows/security-zap.yml

Finding severity map

ZAP uses a numeric risk code:

riskcode ZAP label Our action
3 HIGH Auto-file GitHub issue, severity:high + area:security; block PR (advisory)
2 MEDIUM Log in artifact; post in PR comment; no auto-issue; triage within 1 week
1 LOW Log in artifact only; no action required
0 INFO Log in artifact only

Step 1 — Find the artifacts

  1. Go to the Actions run that fired (link is in the auto-filed issue body or PR comment).
  2. Scroll to the bottom of the run page → Artifacts.
  3. Download zap-antlers-report-<run_id> or zap-api-report-<run_id>.
  4. Open report_html.html for a human-readable summary, or report_json.json for machine-parseable details.

Step 2 — Triage a HIGH alert

For each HIGH alert in the report:

  1. Confirm the URL is reachable. ZAP sometimes fires on redirect chains or error pages. Check whether the finding URL is a real application endpoint.

  2. Check the rule ID against the .zap/rules.tsv IGNORE list. If the rule should be ignored and isn't yet, add it with a comment and open a PR.

  3. Confirm exploitability in the Raxx threat model: - Is the affected route user-accessible or internal-only? - Does it handle user-supplied input? - Is there a realistic attack vector given current auth model (CF Access + header-based API auth)?

  4. Act on the finding: - Exploitable → assign the auto-filed issue to a developer; add ready-for-dev label; link from Epic #81 if it's a systemic issue. - False positive → close the auto-filed issue with a comment explaining why; add an IGNORE entry in .zap/rules.tsv with rationale. - Needs more context → leave needs-grooming, tag card-groomer for a grooming pass.

Step 3 — Fix and verify

After a code fix is merged:

  1. Trigger a manual ZAP run via workflow_dispatch with the staging URL to confirm the finding is resolved.
  2. Close the GitHub issue once the manual run is clean.
  3. If you added a temporary IGNORE in .zap/rules.tsv to suppress the finding while the fix was in flight, remove the IGNORE entry in the same PR as the fix.

Suppressing a false positive

Edit .zap/rules.tsv — add a line:

<rule-id>\tIGNORE

Always add a comment on the line above explaining why the rule is a false positive for Raxx. Open a PR; the security_response.md process applies.

Known false positives are documented in .zap/rules.tsv with full rationale.

DO NOT scan production

The scan is configured to target staging URLs only. Never add production hostnames (app.raxx.app, raxx-console-prod.herokuapp.com, etc.) to the workflow. Scanning prod can:

If a finding must be verified against prod behavior: reproduce it in a local environment or against staging with production-equivalent config.

Contacts and escalation