Webhooks, Slack, and CI: Connecting AI Pentest Results to Your Incident Workflow
Pentestas Team
Security Analyst

Findings are events. Events fan out to your incident-response stack.
In Detail
The event model
Pentestas emits the following events:
| Event | Payload |
|---|---|
scan.created | scan_id, tenant_id, target_url, created_at |
scan.started | scan_id, started_at |
scan.progress | scan_id, phase, message (throttled, not per-event) |
scan.completed | scan_id, findings_count, severity_breakdown, target_url, timestamp |
scan.failed | scan_id, error |
finding.created | finding (full schema) |
finding.status_changed | finding_id, from, to, changed_by |
agent.connected | agent_id, hostname |
agent.disconnected | agent_id, reason |
Subscribe to any subset per webhook. Events are signed with HMAC-SHA256 + your per-webhook secret so you can verify authenticity before trusting them.
In Detail
Slack — zero-code
Fastest integration. Settings → Integrations → Slack → paste an incoming-webhook URL → save. A test message fires immediately to confirm the URL is live. From then on, every scan completion posts a rich message:
🚨 Scan complete: https://app.example.com
Findings: 42 total (3 critical, 8 high, 15 medium, 16 low)
Chain: "Path traversal → SSH keys → lateral" (CRITICAL)
[View results →]Colour:
- Red — any CRITICAL.
- Orange — HIGH but no CRITICAL.
- Green — no HIGH/CRITICAL.
Pro+ adds:
- **Only alert on new CRITICAL / HIGH*— throttles noisy scans.
- **Thread under scheduled-scan parent*— long-running schedule posts one parent; each run replies in the thread. Channel stays clean.
- **Custom Go-template body*—
{{.Scan}},{{.Findings}},{{.TopChain}}variables for custom formatting.
In Detail
Webhooks — arbitrary HTTPS
For any destination Slack doesn't cover, outbound webhooks drop JSON on any HTTPS URL. Configure in Settings → Webhooks:
- URL (HTTPS enforced).
- Events subscribed.
- HMAC secret.
- Description (freeform).
Pentestas sends a webhook.test event on save to confirm. Delivery failures (5xx, timeout > 10s) retry with exponential backoff: 30s, 2min, 10min, 1h, 6h, 24h. After 6 failed attempts, the delivery goes to the dead-letter queue + an in-app notification fires. The webhook itself isn't disabled — future events still fire.
Verification
Every request carries an X-Pentestas-Signature header:
X-Pentestas-Signature: sha256=<hex>Where <hex> is HMAC-SHA256(secret, raw_body). Verify in your handler before trusting anything:
import hmac, hashlib
def verify(secret: str, sig_header: str, body: bytes) -> bool:
expected = hmac.new(secret.encode(), body, hashlib.sha256).hexdigest()
provided = sig_header.split("=", 1)[1]
return hmac.compare_digest(expected, provided)Always compare_digest — string equality leaks timing information.
In Detail
Jira — ticket-per-finding
Webhook handler that POSTs to Jira's REST API on finding.created:
@app.post("/pentestas-webhook")
def handle():
event = request.get_json()
if event["event"] != "finding.created":
return "ok", 200
finding = event["finding"]
if finding["severity"] not in ("CRITICAL", "HIGH"):
return "ok", 200
jira_client.create_issue(
project=os.environ["JIRA_PROJECT"],
summary=f"[{finding['severity']}] {finding['title']}",
description=f"""
Endpoint: {finding['endpoint']}
CVSS: {finding['cvss_score']} ({finding['cvss_vector']})
CWE: {finding['cwe_id']}
OWASP: {finding['owasp_category']}
Evidence:
{finding['evidence']}
Remediation:
{finding['recommendation']}
Pentestas: https://app.pentestas.com/scan-detail/{event['scan_id']}#finding-{finding['id']}
""",
labels=["pentestas", finding["vuln_type"].lower()],
priority="Highest" if finding["severity"] == "CRITICAL" else "High",
)
return "ok", 200On finding.status_changed → fixed, close the Jira ticket. Clean bi-directional flow.
In Detail
PagerDuty — page on CRITICAL
@app.post("/pentestas-webhook")
def handle():
event = request.get_json()
if event["event"] != "scan.completed":
return "ok", 200
if event.get("severity_breakdown", {}).get("CRITICAL", 0) == 0:
return "ok", 200
pagerduty.trigger_incident(
service=os.environ["PD_SERVICE_KEY"],
incident_key=f"pentestas-{event['scan_id']}",
summary=f"Pentestas: CRITICAL finding on {event['target_url']}",
details=event,
)
return "ok", 200De-dupe with the incident_key = scan_id pattern so re-firing on a subsequent scan against the same target doesn't spam.
Scanning
ServiceNow — incident-per-scan
The same shape as Jira but pointed at ServiceNow's Table API. Enterprise customers often add ServiceNow-specific fields (business_service, assignment_group, category) on top of the core schema.
Security
GitHub Security tab — SARIF export
- name: Pentestas scan
env:
PENTESTAS_API_KEY: ${{ secrets.PENTESTAS_API_KEY }}
run: |
pentestas start -u https://staging-${{ github.sha }}.example.com -c .pentestas/scan.yaml -w 30m
scan_id=$(pentestas list --status completed --limit 1 | head -1 | awk '{print $1}')
curl -H "X-API-Key: ${PENTESTAS_API_KEY}" \
"https://app.pentestas.com/api/scans/${scan_id}/report?format=sarif" \
-o pentestas.sarif
- name: Upload SARIF
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: pentestas.sarifFindings light up in the repo's Security tab with file-level annotations (when white-box mode supplied source-code citations). Engineers see them in the same UI as their CodeQL, Dependabot, and secret-scanning findings.
In Detail
SIEM integration (Splunk, Sentinel, Datadog)
Every SIEM supports HTTP event-collector endpoints. Webhook → HEC URL:
@app.post("/pentestas-webhook")
def handle():
event = request.get_json()
requests.post(
os.environ["SPLUNK_HEC_URL"],
json={
"source": "pentestas",
"sourcetype": "pentestas:" + event["event"],
"event": event,
},
headers={"Authorization": f"Splunk {os.environ['SPLUNK_HEC_TOKEN']}"},
)
return "ok", 200Scan-completion rate, finding-creation trend, average-time-to-fix per severity — all become native Splunk dashboards with a few SPL queries against the resulting event stream.
In Detail
Rate limits + reliability
- 50 events / minute per webhook URL.
- **10,000-event buffer.*If your destination is down for a while, Pentestas buffers up to 10K events; past that, oldest events drop.
- **Successful response:*any 2xx. Anything else (including 3xx redirects) is treated as failure and retried.
- **Idempotency:*every event includes an
event_id. Destinations should de-dupe onevent_id— replays happen.
In Detail
Delivery log
Settings → Webhooks → click a webhook → Delivery log. Shows the last 100 deliveries with request / response / latency. Click any to see the full JSON body. Replay button re-fires a specific delivery if your destination was down or had a transient bug.
This is the single most-used debugging feature when wiring a new integration. Expect to use it every time you add a new webhook.
By Industry
Industry scenarios
Fintech
Chain — finding → Jira → engineer fix → Slack notification on resolve → SIEM trend update. Full lifecycle visible to every stakeholder. Compliance officer looks at the SIEM dashboard quarterly; CISO looks at the Slack summary; engineers work in Jira. Each consumer gets their native interface.
Medtech
Chain — CRITICAL finding → PagerDuty page → incident opened in ServiceNow → HIPAA-adjacent review triggered. Fast triage on the PHI-sensitivity findings. Monthly trend reporting to the HIPAA compliance programme manager via SIEM.
Legaltech
Chain — client-facing attestation need → scheduled PDF export via webhook → store in client-share drive. Automated evidence generation for enterprise RFP responses.
Banks + insurance
Chain — scan completion → SIEM ingest → risk-management-system trend → quarterly risk-committee dashboard. Board-visible testing cadence without manual curation.
In Detail
Getting started
- For Slack: 2 minutes. Paste incoming-webhook URL. Done.
- For Jira / PagerDuty: 30 minutes of handler code. Ship it to an existing HTTPS endpoint (AWS Lambda, Cloudflare Worker, dedicated service).
- For SIEM: 15 minutes. Point the webhook at your HEC URL.
- For GitHub: one CI job change. See the CLI post.
The integration pattern scales to every downstream system. Pentestas doesn't care where findings go; the API surface makes sure they can go wherever your programme needs.
Wire your first Pentestas integration
Register, run a scan, add a Slack webhook. First finding lands in your channel the same day.
Start your AI pentestMore Reading
Further reading

Alexander Sverdlov
Founder of Pentestas. Author of 2 information security books, cybersecurity speaker at the largest cybersecurity conferences in Asia and a United Nations conference panelist. Former Microsoft security consulting team member, external cybersecurity consultant at the Emirates Nuclear Energy Corporation.