Exports · 5 min read

Slack, Discord, Teams & JSON webhooks

Per-sink webhook delivery for new findings. Slack gets Block Kit formatting, Discord gets embeds, Teams gets an Office 365 connector card, and everything else gets a generic JSON envelope. Live Feed and MSP tiers.

Noxen Settings → Webhooks pane showing existing webhook entries with sink type, URL, minimum severity filter, and the Add webhook button.
Settings → Webhooks. Each row is a configured sink with its severity filter and a Send test payload button.

Add a webhook

Settings → Webhooks → Add webhook. Fields:

Sink
One of Slack, Discord, Microsoft Teams, or Generic JSON. Picks the payload shape Noxen sends.
URL
The webhook URL the sink gives you. For Slack: Apps → Manage → Custom Integrations → Incoming Webhooks → Add Configuration. For Discord: Server Settings → Integrations → Webhooks → New Webhook. For Teams: Channel → … → Connectors → Incoming Webhook. For Generic JSON: any HTTPS endpoint that accepts a POST.
Minimum severity
Critical / High / Medium / Low / Info. Findings below the threshold don't fire. Default critical for primary alerting channels; Medium for diagnostic / "everything" channels.
Label (optional)
Display name shown in the webhook list. #sec-alerts, oncall iPhone Discord, Splunk HEC fallback.

Per-sink payload shapes

Slack (Block Kit)

{
  "blocks": [
    { "type": "header",
      "text": { "type": "plain_text", "text": "[CRITICAL] CVE-2024-6387 on edge-nuc" } },
    { "type": "section",
      "text": { "type": "mrkdwn",
        "text": "*Package:* openssh-server 9.2p1\n*CVSS:* 8.1\n*Detail:* regreSSHion signal handler race allows unauthenticated RCE." } },
    { "type": "actions",
      "elements": [
        { "type": "button", "text": { "type": "plain_text", "text": "Open in Noxen" },
          "url": "noxen://host/uuid" }
      ] }
  ]
}

Discord (embeds)

{
  "embeds": [{
    "title": "[CRITICAL] CVE-2024-6387 on edge-nuc",
    "description": "regreSSHion signal handler race allows unauthenticated RCE.",
    "color": 14816800,
    "fields": [
      { "name": "Package", "value": "openssh-server 9.2p1", "inline": true },
      { "name": "CVSS", "value": "8.1", "inline": true }
    ],
    "footer": { "text": "Noxen — homelab security from your Mac" },
    "timestamp": "2026-04-27T03:14:22Z"
  }]
}

Microsoft Teams (Office 365 connector card)

{
  "@type": "MessageCard",
  "@context": "https://schema.org/extensions",
  "summary": "Noxen finding: CVE-2024-6387 on edge-nuc",
  "themeColor": "E11900",
  "title": "[CRITICAL] CVE-2024-6387 on edge-nuc",
  "sections": [{
    "facts": [
      { "name": "Package", "value": "openssh-server 9.2p1" },
      { "name": "CVSS", "value": "8.1" }
    ],
    "text": "regreSSHion signal handler race allows unauthenticated RCE."
  }]
}

Generic JSON

{
  "host": { "id": "uuid", "name": "edge-nuc", "address": "10.0.1.42", "tags": ["homelab"] },
  "scan": { "id": "uuid", "scanned_at": "2026-04-27T03:14:22Z" },
  "findings": [
    {
      "id": "uuid", "severity": "critical", "category": "cve",
      "title": "CVE-2024-6387", "detail": "...",
      "cve_id": "CVE-2024-6387", "cvss_v3": 8.1,
      "package": "openssh-server 9.2p1",
      "remediation": "apt-get install --only-upgrade openssh-server"
    }
  ]
}

The generic envelope is the most flexible — point it at any service that accepts a JSON POST (a custom Cloudflare Worker, a Slack-but-via-an-aggregator, your own backend), and inspect the body to decide what to do with it.

Test payload

Each webhook row has a Send test payload button. Clicking it generates a synthetic critical finding ("CVE-EXAMPLE-2026-1234 on test-host") and POSTs it to the configured URL. Use to verify the URL is reachable, the sink formatting renders correctly, and the channel is the one you meant.

When webhooks fire

Webhooks do not fire on findings that already existed in the previous scan — only on new findings. This matches the diff-from-yesterday philosophy: alert on change, not on steady state.

Tier requirements

Webhooks require Live Feed or MSP. Lower tiers can configure webhooks (the UI is not gated) but a banner explains they won't fire at runtime. Pricing tiers →