Agent skill

Signal Sciences Webhooks Skill

Receive and verify Signal Sciences (Fastly Next-Gen WAF) generic webhooks. Use when setting up Signal Sciences or Fastly Next-Gen WAF webhook alert handlers, debugging X-SigSci-Signature verification, or handling events like flag, agentAlert, loggingModeChanged, and ruleCreated.

Install this skill

npx skills add hookdeck/webhook-skills --skill signal-sciences-webhooks


Signal Sciences is now the Fastly Next-Gen WAF. Its generic webhook integration (alert) posts JSON notifications for selected workspace (site) activity, such as a flagged IP address or an agent alert.

When to Use This Skill

  • How do I receive Signal Sciences or Fastly Next-Gen WAF webhooks?
  • How do I verify the X-SigSci-Signature header?
  • Why is my Signal Sciences webhook signature verification failing?
  • How do I handle flag or agentAlert events?
  • Where do I find or rotate the signing key for a generic webhook?

Verification (core)

Fastly sends X-SigSci-Signature: the hex HMAC-SHA256 digest of the raw JSON body, keyed with the signing key generated for the integration (used as a plain string). There is no timestamp and no prefix. Compare timing-safe.

Node:

const crypto = require('crypto');

function verify(rawBody, signatureHeader, signingKey) {
  if (!signatureHeader) return false;
  const expected = crypto.createHmac('sha256', signingKey).update(rawBody).digest('hex');
  try {
    return crypto.timingSafeEqual(Buffer.from(signatureHeader.trim().toLowerCase()), Buffer.from(expected));
  } catch {
    return false;
  }
}

Python:

import hmac, hashlib

def verify(raw_body: bytes, signature_header: str, signing_key: str) -> bool:
    if not signature_header:
        return False
    expected = hmac.new(signing_key.encode(), raw_body, hashlib.sha256).hexdigest()
    return hmac.compare_digest(signature_header.strip().lower(), expected)

For complete handlers with route wiring, event dispatch, and tests, see:

Fastly publishes no SDK for verification, so all examples use the manual HMAC check above.

Payload Shape

The event name is the type field in the JSON body (there is no event-type header):

{
  "created": "2024-02-09T21:08:21.31644377Z",
  "type": "flag",
  "payload": { "ID": "...", "SiteID": "...", "Slug": "site.example" },
  "link": "dashboard link to event",
  "workspaceId": "www.mysite.com"
}

Common Event Types

typeDescription
flagAn IP address was flagged
expireFlagAn IP address flag was manually expired
agentAlertAn agent alert was triggered
loggingModeChangedAgent mode (Blocking, Not Blocking, Off) changed
ruleCreated / ruleUpdated / ruleDeletedA request rule changed
listCreated / listUpdated / listDeletedA list changed
customAlertCreated / customAlertUpdated / customAlertDeletedA custom alert changed

See references/overview.md for the full list of activity types.

Important Headers

HeaderDescription
X-SigSci-SignatureHex HMAC-SHA256 of the raw body
Content-Typeapplication/json

Environment Variables

SIGNAL_SCIENCES_SIGNING_KEY=your_signing_key   # Reveal/Rotate on the integration in the console

Local Development

# Start tunnel (no account needed)
npx hookdeck-cli listen 3000 signal-sciences --path /webhooks/signal-sciences

Reference Materials


Repository

hookdeck/webhook-skills

v0.1.0 · MIT · Updated Nov 2, 2026

View on GitHub →