Webhooks
Cerberon can post a signed JSON message to one HTTPS endpoint whenever a selected event occurs. Use it to feed a SIEM, open tickets, or relay alerts to chat through your own receiver.
Configure
Section titled “Configure”Go to Settings > Integrations and open Outbound Webhook. Select Enable the webhook, enter the Destination URL, choose the Events to send, set a signing secret and save. Send test event delivers a test and shows the response status and latency.
The secret is sealed at rest and never shown again. Webhook URLs on a private network address are refused unless an administrator allows private destinations. The connection is pinned to the addresses checked when you saved, so a later DNS change cannot redirect deliveries.
Through the API:
curl -sSf -X PUT "$CERBERON_URL/api/settings/integrations/webhook" \ -H "Authorization: Bearer $CERBERON_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "enabled": true, "url": "https://siem.example.com/hooks/cerberon", "events": ["scan_completed", "scan_failed", "risk_acceptance_expired"], "secret": "<signing secret>", "allow_private": false }'This needs an administrator’s read-and-write token.
Events
Section titled “Events”| Event | Sent when |
|---|---|
scan_completed |
A scan finishes. |
scan_failed |
A scan fails. |
scan_refused |
A scan, including a scheduled one, is refused at start. |
scan_stopped |
A scan is stopped by a user or its time limit. |
finding_assigned |
A finding is assigned to someone. |
risk_acceptance_expired |
An accepted risk reaches its expiry and the finding reopens. |
update_available |
A new release is available. |
licence_expiring, licence_expired |
The licence is about to expire, or has expired. |
certificate_expiring |
The instance’s TLS certificate is about to expire. |
disk_low |
Free disk falls below the warning threshold. |
maintenance |
An update or maintenance operation starts. |
Delivery format
Section titled “Delivery format”Each delivery is a POST with a JSON body:
{ "id": "<delivery id>", "type": "scan_completed", "created_at": "2026-10-30T09:00:00.000Z", "data": { }}| Header | Value |
|---|---|
X-Cerberon-Event |
The event type |
X-Cerberon-Delivery |
The delivery ID, for de-duplication |
X-Cerberon-Timestamp |
The event time |
X-Cerberon-Signature |
sha256= followed by the hex HMAC-SHA256 of the raw body, keyed with your secret |
A delivery times out after 5 seconds.
Verify the signature
Section titled “Verify the signature”Compute the HMAC over the raw request body, before parsing it, and compare in constant time.
import { createHmac, timingSafeEqual } from "node:crypto"
export function verify(rawBody, header, secret) { const expected = "sha256=" + createHmac("sha256", secret).update(rawBody).digest("hex") return header.length === expected.length && timingSafeEqual(Buffer.from(header), Buffer.from(expected))}import hashlibimport hmac
def verify(raw_body: bytes, header: str, secret: str) -> bool: expected = "sha256=" + hmac.new(secret.encode(), raw_body, hashlib.sha256).hexdigest() return hmac.compare_digest(header, expected)