Setup webhooks
Configure Slack, PagerDuty, Webex, and generic HMAC webhooks so the gateway can ping a chat or incident channel when high-severity events fire.
defenseclaw setup webhook manages the notifier webhooks the gateway dispatches when a guardrail or asset-policy event clears your minimum-severity threshold. Four destinations are supported out of the box; every one of them is configurable interactively or via a fully-flagged non-interactive form.
Notifiers vs audit sinks — important
There are two webhook surfaces, and they are intentionally separated:
- Notifiers (
defenseclaw setup webhook) — chat/incident pings shaped to the destination's API (Slack blocks, PagerDuty Events v2, Webexmessages, or generic JSON). Severity-gated, deduped, exactly the events you'd page someone for. This page. - Audit sinks (
defenseclaw setup observability add webhook) — every event the gateway emits, posted as JSONL. No severity gate; intended for SIEMs and data lakes.
Pick the surface that matches the consumer. Most installs run one notifier (Slack) and zero or one audit sinks.
The four webhook types
Prop
Type
Three worked examples
Slack incoming webhooks carry the secret in the URL itself, so you do not need a --secret-env:
defenseclaw setup webhook add slack \
--url https://hooks.slack.com/services/T000/B000/XXXXXX \
--min-severity HIGH \
--non-interactiveTest it without paging the channel by using --dry-run, then live-fire when you're happy:
defenseclaw setup webhook test slack-hooks-slack-com --dry-run
defenseclaw setup webhook test slack-hooks-slack-comPagerDuty Events v2 needs a routing key. Store the secret in an env var, point the webhook at its name:
export DEFENSECLAW_PD_ROUTING_KEY="R0…XYZ"
defenseclaw setup webhook add pagerduty \
--name pd-prod \
--url https://events.pagerduty.com/v2/enqueue \
--secret-env DEFENSECLAW_PD_ROUTING_KEY \
--min-severity HIGH \
--non-interactiveThe dispatcher reads the live env value at call time, so rotating the routing key is a single export away.
For SIEMs / SOAR platforms that prefer a generic POST with a verifiable signature:
export DEFENSECLAW_SIEM_SECRET="some-shared-secret"
defenseclaw setup webhook add generic \
--name siem \
--url https://siem.example.com/defenseclaw \
--secret-env DEFENSECLAW_SIEM_SECRET \
--events policy_block,judge_block,asset_policy_deny \
--min-severity MEDIUM \
--non-interactiveThe receiver validates the HMAC by recomputing HMAC-SHA256(secret, body) and comparing it to the X-DefenseClaw-Signature header.
All seven subcommands
Prop
Type
Flag reference for add
| Flag | Default | Notes |
|---|---|---|
--name <id> | derived from type + URL host | Friendly identifier shown in list and audit. |
--url <url> | (required) | Validated against the SSRF guard at write time and again at delivery. |
--secret-env <ENV> | type-specific (see below) | The name of an env var, never the literal secret. The CLI rejects values that look like real secrets. |
--room-id <id> | (required for webex) | Webex room/space identifier. |
--min-severity LOW|MEDIUM|HIGH|CRITICAL | HIGH | Events below the floor are dropped. |
--events a,b,c | (all categories) | Allow-list — useful when a receiver only cares about, say, policy_block. |
--timeout-seconds <n> | 5 | Per-delivery timeout. |
--cooldown-seconds <n> | 300 (runtime default) | Dedup window. 0 disables dedup; omit to use the runtime default. |
--enabled / --disabled | --enabled | Initial state. |
--dry-run | off | Print the YAML diff without writing. |
--non-interactive | off | Required for CI; missing required fields exit non-zero with a error: --foo is required message. |
Per-type --secret-env defaults:
| Type | Default --secret-env |
|---|---|
slack | (none — secret is in the URL) |
pagerduty | DEFENSECLAW_PD_ROUTING_KEY |
webex | DEFENSECLAW_WEBEX_TOKEN |
generic | none; you'll be asked whether to sign with HMAC, default DEFENSECLAW_WEBHOOK_SECRET |
SSRF guard
Every URL is validated against the same SSRF guard the Go gateway runs at delivery time:
- TLD, scheme (
https://only by default), and host parse cleanly. - Resolves to a public IP. RFC1918, link-local, and loopback are rejected unless you explicitly opt in by exporting
DEFENSECLAW_WEBHOOK_ALLOW_LOCALHOST=1. - No userinfo (
https://user:pass@…) — credentials belong in--secret-env.
The validator runs both at add time (early failure) and at delivery time (catches hand-edits to config.yaml that would otherwise reject events at runtime).
Verifying a webhook with test
test ships a synthetic event with a unique event-ID per invocation, which means receivers cannot dedup it:
defenseclaw setup webhook test pd-prodThe output includes:
- The formatted payload bytes count and a 160-byte preview.
- Every header DefenseClaw sent (including any HMAC signature for
generic). - The HTTP status returned by the receiver.
- An audit-log entry tagged
setup-webhook test name=pd-prod ok=true.
For the dry-run rehearsal:
defenseclaw setup webhook test pd-prod --dry-run— the payload is formatted (so you can copy/paste it into your receiver's playground) without making the HTTP call.
Common gotchas
Reference
cli/defenseclaw/commands/cmd_setup_webhook.py— every subcommand, validator, and helper.internal/gateway/webhook.go— the dispatcher, dedup logic, and HMAC implementation.- Reference → CLI — the CLI command catalog.
- Observability → Splunk — for the audit-sink path (every event, no severity floor).
Setup MCP scanner
Behavioural scan of every Model Context Protocol server an agent might call. DefenseClaw wraps cisco-ai-mcp-scanner to surface hidden tool intents and shadow capabilities, and writes verdicts into the same mcp_actions admission policy as the watcher.
Setup registries
Subscribe DefenseClaw to public or internal skill / MCP catalogs. Sources are fetched, scanned, and clean entries are auto-promoted into asset_policy so admission decisions can attribute the rule back to its origin.