Safeguard.sh Documentation Center

Webhooks & Events

Subscribe to Safeguard events — findings, scans, remediations, attestations, audit — and drive your own automations.

Webhooks & Events

Safeguard publishes every meaningful state change as an event. Subscribe via webhook, stream via Kafka / Kinesis / Pub-Sub, or poll the events API. Every webhook payload is signed so you can verify the sender.

Event Catalog

Events follow the shape <domain>.<subject>.<verb>.

Findings

EventWhen
findings.vulnerability.createdNew vulnerability finding on any asset
findings.vulnerability.severity_changedEPSS / KEV / CVSS update changed severity bucket
findings.vulnerability.reachability_changedReachability classification updated
findings.vulnerability.suppressedException granted or false-positive confirmed
findings.vulnerability.resolvedUpgrade / patch / removal verified
findings.secret.createdNew secret detected
findings.secret.verifiedSecret confirmed live via issuer API
findings.secret.revokedSecret revocation completed
findings.license.createdNew license-policy violation
findings.malware.createdEagle flagged a malicious artifact

Scans

EventWhen
scan.startedScan of any asset begins
scan.completedScan completes; payload includes new findings summary
scan.failedScan errored; payload includes failure reason

Zero-Days

EventWhen
zero_day.publishedSafeguard publishes a new SG-YYYY-NNNNN advisory
zero_day.affecting_tenantA published zero-day affects an asset in your tenant
zero_day.embargo_endedCVE has been assigned and the advisory is now public

Remediation

EventWhen
remediation.plan_createdGriffin generated a plan
remediation.pr_openedAuto-fix PR opened in your repo
remediation.pr_mergedAuto-fix PR merged upstream
remediation.pr_closedAuto-fix PR closed without merge
remediation.self_heal.startedSelf-heal container rebuild started
remediation.self_heal.promotedSelf-heal image promoted to registry tag
remediation.self_heal.rolled_backSelf-heal rollback triggered

Attestations

EventWhen
attestation.createdNew attestation published
attestation.verification_failedAttestation verification failed (admission, CI, etc.)

Workflows

EventWhen
workflow.run.startedWorkflow run began
workflow.run.completedWorkflow run finished successfully
workflow.run.failedWorkflow run failed

Policy

EventWhen
policy.violationA BLOCK or WARN fired
policy.exception_grantedAn exception was approved
policy.exception_expiredA time-boxed exception expired

Asset & Vendor

EventWhen
asset.discoveredNew asset found (repo, image, model, workload, SBOM)
asset.ungovernedAsset flagged as missing owner / SBOM / governance
vendor.sbom_receivedNew vendor SBOM uploaded
vendor.risk_score_changedTPRM risk score threshold crossed

Audit

EventWhen
audit.actionAny state-mutating action in the audit log

Delivery Options

HTTP Webhook

safeguard webhooks create \
  --url https://example.com/sg \
  --events findings.vulnerability.created,findings.secret.verified \
  --secret $(openssl rand -hex 32) \
  --filter 'severity in ["critical","high"] and env == "production"'

Payload:

{
  "id": "evt_01J...ABC",
  "type": "findings.vulnerability.created",
  "created_at": "2026-04-23T12:34:56.789Z",
  "data": { "finding": { ... }, "asset": { ... } },
  "tenant": "acme",
  "api_version": "2026-01-01"
}

Every payload ships with headers:

  • X-Safeguard-Signature: v1,t=<unix>,s=<hex hmac sha-256>
  • X-Safeguard-Event-Id: the event ID (idempotent).
  • X-Safeguard-Delivery-Attempt: attempt count (1 for first delivery).
  • X-Safeguard-Api-Version.

Streams

Push events directly into your stream:

  • AWS Kinesis Data Streams / Firehose — direct integration.
  • Azure Event Hubs — direct integration.
  • GCP Pub/Sub — direct integration.
  • Confluent Cloud / Apache Kafka — via webhook sink.
  • NATS — via webhook sink.
  • Redis Streams — via webhook sink.

SSE / WebSocket

For interactive dashboards:

const es = new EventSource("https://api.safeguard.sh/v1/events/stream", {
  headers: { Authorization: `Bearer ${token}` }
});
es.addEventListener("findings.vulnerability.created", (e) => { ... });

Polling

safeguard events list --after "2026-04-23T00:00:00Z" --type findings.*.created

Filters

Every subscription can be filtered server-side using a subset of the policy expression language:

severity in ["critical","high"]
AND env == "production"
AND NOT finding.kev == false

Server-side filters minimize traffic and reduce webhook noise.

Reliability

  • At-least-once delivery. Consumers must handle duplicates by X-Safeguard-Event-Id.
  • Exponential backoff retries — 11 attempts over 24 hours (1s, 5s, 30s, 1m, 5m, 15m, 1h, 3h, 6h, 12h, 24h).
  • Dead-letter queue — undelivered events land in a DLQ you can replay from the UI or API.
  • SLA — 99.9% delivery within 10 seconds for Pro, 99.99% for Enterprise.

Signature Verification

import hmac, hashlib, time

def verify(secret: bytes, header: str, body: bytes) -> bool:
    parts = dict(p.split("=", 1) for p in header.split(",", 1)[1].split(","))
    ts, sig = parts["t"], parts["s"]
    # reject events older than 5 min (replay guard)
    if abs(time.time() - int(ts)) > 300: return False
    expected = hmac.new(secret, f"{ts}.".encode() + body, hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, sig)
import { createHmac, timingSafeEqual } from "crypto";

export function verify(secret: string, header: string, body: Buffer): boolean {
  const [_, tsPart, sigPart] = header.split(",");
  const ts = tsPart.slice(2);
  const sig = sigPart.slice(2);
  if (Math.abs(Date.now() / 1000 - Number(ts)) > 300) return false;
  const expected = createHmac("sha256", secret).update(`${ts}.`).update(body).digest("hex");
  return timingSafeEqual(Buffer.from(expected), Buffer.from(sig));
}

Idempotency

  • Each event has a stable id.
  • Consumers must deduplicate by ID; the guarantee is at-least-once, not exactly-once.
  • Within a single event type, Safeguard guarantees monotonically increasing created_at for a given subject (finding, asset, workflow run, etc.).

Testing

Trigger synthetic events for testing without triggering actual state changes:

safeguard webhooks test --endpoint https://example.com/sg --type findings.vulnerability.created

The test payload has a "test": true field so your consumer can ignore it in production pipelines.

Observability

The Webhooks page shows per-endpoint:

  • Delivery attempts (success, retry, failed).
  • Average latency.
  • DLQ size.
  • Last 1000 deliveries with request / response bodies (scrubbed of secrets).

API

safeguard webhooks list
safeguard webhooks create --url ... --events ...
safeguard webhooks update <id> --filter '...'
safeguard webhooks delete <id>
safeguard events list
safeguard events show <id>
safeguard events replay <id>   # replays to all subscribed endpoints
  • API Reference — full REST API.
  • SDKs — language SDKs with built-in signature verification.
  • Workflows — Safeguard's own consumer of these events.

On this page