Skip to content

CI/CD automation

You can wire BestDefense into a CI/CD pipeline to scan on every release and fail the build when serious issues appear. This page shows the end-to-end pattern with the REST API; for authentication and tokens, start with API access & tokens.

All examples use the base URL https://app.bestdefense.io and assume your token is in BD_API_TOKEN.

A security gate is four steps: trigger → poll → fetch → decide.

  1. Trigger a scan against your site.
  2. Poll the report until it completes.
  3. Fetch the findings (a risk summary by severity).
  4. Decide — pass or fail the build based on the counts.

This script runs a quick Vortex scan, waits for it, and exits non-zero if there are any critical or high findings:

#!/usr/bin/env bash
set -euo pipefail
BD="https://app.bestdefense.io"
AUTH="Authorization: Bearer ${BD_API_TOKEN:?set BD_API_TOKEN}"
SITE_HOST="example.com" # a verified site in your org
# 1. Find the site's UUID by hostname
site_id=$(curl -fsS -H "$AUTH" "$BD/api/sites" \
| jq -r --arg h "$SITE_HOST" '.data.sites[] | select(.hostname == $h) | .id')
# 2. Trigger an Analog (quick) Vortex scan; capture the new report's UUID
report_id=$(curl -fsS -X POST -H "$AUTH" -H "Content-Type: application/json" \
"$BD/api/report/create/for-target/$site_id" \
-d '{
"options": {
"security": {
"enabled": true,
"options": {
"vortexType": "analog",
"testingType": "web",
"scanIntensity": "quick"
}
}
}
}' | jq -r '.id')
echo "Started report $report_id"
# 3. Poll progress until the scan completes
until [ "$(curl -fsS -H "$AUTH" "$BD/api/report/$report_id/progress" \
| jq -r '.data.isCompleted')" = "true" ]; do
echo " scanning…"; sleep 30
done
# 4. Resolve the security report's numeric id from the overview
secr_id=$(curl -fsS -H "$AUTH" "$BD/api/report/$report_id/overview" \
| jq -r '.data.security.id')
# 5. Pull the risk summary by severity
read -r crit high < <(curl -fsS -H "$AUTH" \
"$BD/api/report/vortex/$secr_id/alerts" \
| jq -r '.data.riskSummary | "\(.critical) \(.high)"')
echo "Critical: $crit High: $high"
# 6. Fail the build on any critical or high finding
if [ "$crit" -gt 0 ] || [ "$high" -gt 0 ]; then
echo "::error::Security gate failed — $crit critical, $high high findings"
exit 1
fi
echo "Security gate passed"

Store the token as a repository secret (BD_API_TOKEN) and run the script as a step:

jobs:
security-gate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: BestDefense scan gate
env:
BD_API_TOKEN: ${{ secrets.BD_API_TOKEN }}
run: ./scripts/bestdefense-gate.sh

The same approach works in GitLab CI/CD (a masked variable + a script job) or any runner that can execute curl and jq.

Instead of triggering on every pipeline run, you can create a recurring schedule once:

POST /api/report/create/for-target/{siteId}/scheduled

The body takes top-level name, frequency, frequencyInterval, a reportConfig object (the same security/scaling shape as create), and optional isEnabled and startDate. Scheduling requires the appropriate plan.

Once you have a finding’s alert ID (from the alerts endpoint), you can open a fix pull request and poll its status:

POST /api/ai/remediation { "securityAlertId": "<alert-uuid>" }
GET /api/ai/remediation/{securityAlertId}/status
GET /api/ai/remediation/{securityAlertId}/pull-requests

Creating a remediation returns 202 Accepted and runs asynchronously. See AI remediation for the bigger picture.

POST /api/network-scans { "tool": "nmap", "targets": ["10.0.0.0/24"] }
GET /api/network-scans (list, paginated)
GET /api/network-scans/{scanId} (status + detail)
GET /api/network-scans/{scanId}/hosts (Nmap scans)
GET /api/network-scans/{scanId}/vulnerabilities (OpenVAS scans)
POST /api/network-scans/{scanId}/cancel

tool is nmap (host discovery) or openvas (vulnerabilities); targets are IPs or CIDR ranges. You can also pass a saved configurationId instead of tool/targets. Reading hosts or vulnerabilities before the scan completes returns 409 Conflict.

The interactive spec at /api/docs is authoritative and always current. The tables below summarize the endpoints most useful for automation.

Method & pathPurpose
GET /api/sitesList your sites (with each site’s UUID and stats).
GET /api/sites/{siteId}/routesList a site’s configured routes (and their UUIDs).
Method & pathPurpose
POST /api/report/create/for-target/{targetId}Create a report (run a scan/test).
POST /api/report/create/for-target/{targetId}/scheduledCreate a recurring schedule.
GET /api/report/{reportId}/progressOverall progress of a report.
GET /api/report/{reportId}/overviewSummary + the per-product sub-report IDs.
GET /api/report/security/{id}/progressDetailed Vortex scan progress.
Method & pathPurpose
GET /api/report/vortex/{vortexReportId}/alertsFindings + risk summary (paginated, filterable by risk, confidence, search).
GET /api/report/vortex/{vortexReportId}/risk-levelsSeverity breakdown.
GET /api/report/vortex/{vortexReportId}/cwe-countsFindings grouped by CWE.
GET /api/report/vortex/{vortexReportId}/dns-scanDNS scan results.
GET /api/report/vortex/{vortexReportId}/whois-scan-resultsWHOIS results.
Method & pathPurpose
GET /api/report/maelstrom/{scalingReportId}/error-ratesError-rate series.
GET /api/report/maelstrom/{scalingReportId}/histogramLatency histogram.
GET /api/report/maelstrom/{scalingReportId}/rpsRequests per second.
GET /api/report/maelstrom/{scalingReportId}/response-codes-by-virtual-usersResponse codes vs. load.
Method & pathPurpose
POST /api/ai/remediationStart a fix for an alert.
GET /api/ai/remediation/{securityAlertId}/statusRemediation status.
GET /api/ai/remediation/{securityAlertId}/pull-requestsPull requests for the alert.
Method & pathPurpose
POST /api/network-scansStart a network scan.
GET /api/network-scansList network scans.
GET /api/network-scans/{scanId}Get one scan’s status/detail.
GET /api/network-scans/{scanId}/hostsDiscovered hosts (Nmap).
GET /api/network-scans/{scanId}/vulnerabilitiesFindings (OpenVAS).
POST /api/network-scans/{scanId}/cancelCancel a running scan.
Method & pathPurpose
GET /api/network-scans/agent/manifestAgent package metadata + a download URL (rate-limited).
GET /api/network-scans/agent/downloadRedirect to the agent download (rate-limited).

The agent endpoints additionally require a token with the agent:download scope, which you select when creating the token.