CI integration

Fail the build on high-severity findings, using the REST API from any runner.

The pattern

Add SteelSuit as a post-deploy check: CI starts a scan against a preview or staging URL via the API, waits for it to finish, and exits non-zero if any finding crosses your severity threshold. There's no CLI to install — it's plain HTTP, so any runner with curl and jq works.

You'll need an sk_ API key (Dashboard → API keys) on a plan with the API enabled (Pro). Store it as a CI secret.

GitHub Actions

- name: SteelSuit security scan
  env:
    STEELSUIT_API_KEY: ${{ secrets.STEELSUIT_API_KEY }}
    TARGET: ${{ env.PREVIEW_URL }}
  run: |
    # 1. Start the scan. A delivery channel is required — email to your
    #    account is the simplest; swap for a webhook to skip the poll loop.
    scan_id=$(curl -fsS -X POST https://steelsuit.com/api/v1/integrations/scans \
      -H "Authorization: Bearer $STEELSUIT_API_KEY" \
      -H "Content-Type: application/json" \
      -d "{\"target\":\"$TARGET\",\"pipeline\":\"fast_scan\",\"delivery\":[{\"type\":\"email\"}]}" \
      | jq -r .scan_id)

    # 2. Poll until the scan reaches a terminal state
    while :; do
      status=$(curl -fsS -H "Authorization: Bearer $STEELSUIT_API_KEY" \
        https://steelsuit.com/api/v1/scans/$scan_id | jq -r .status)
      case "$status" in completed|failed|partial) break ;; esac
      sleep 5
    done

    # 3. Fail the build on any high or critical finding
    n=$(curl -fsS -H "Authorization: Bearer $STEELSUIT_API_KEY" \
      "https://steelsuit.com/api/v1/scans/$scan_id/findings?severity=critical,high" | jq 'length')
    echo "high/critical findings: $n"
    [ "$n" -eq 0 ] || { echo "::error::SteelSuit found $n high/critical issues"; exit 1; }

The same three steps — start, poll, gate — port to GitLab CI or any container runner; only the secret syntax changes.

Webhook instead of polling

If your runner can receive callbacks, swap the email delivery for a webhook and drop the polling loop. SteelSuit POSTs the result envelope (score + counts + result_url) to your endpoint when the scan finishes, signed with your shared secret. See the API reference for the payload shape.

Tips

  • Scan the preview, not production. fast_scan and deep_scan are passive recon, but always point CI at the staging/preview deploy. pentest (active ZAP) isn't available over the API.
  • One scan per domain at a time. Starting a second scan for a domain that already has one queued or running returns 409 — let the previous one finish, or scope CI to main.
  • Quotas add up. A scan per PR consumes your plan's per-period quota. Scope to main or release branches if you're close to the cap.