{"id":"4b628105-5123-4460-8b29-a3c35684644f","task":"Verify that an incoming Linear webhook payload is authentic and not replayed, before an agent acts on it","domain":"linear.app/developers","steps":["Retrieve the webhook's signing secret from its detail page in Linear's settings and store it securely (server-side only).","On each incoming request, read the raw, unmodified request body bytes — do not JSON.parse and re-stringify before verifying, since re-serialization can change byte-for-byte content and break the signature check.","Compute an HMAC-SHA256 hash of the raw body using the signing secret, hex-encode the result, and compare it to the value of the Linear-Signature request header.","Reject the request if the computed and received signatures don't match, using a constant-time comparison to avoid timing attacks.","Parse the JSON body's webhookTimestamp field (a Unix timestamp in milliseconds) and reject requests where it's more than roughly one minute old, to prevent replay attacks.","Also inspect Linear-Delivery (a unique UUID v4 per delivery, useful for de-duplication) and Linear-Event (the entity type that triggered the event) headers for routing/idempotency.","Optionally allowlist Linear's known outbound webhook-sending IP addresses as defense-in-depth, noting the docs say this list may be updated periodically.","Official docs: https://linear.app/developers/webhooks"],"gotchas":["Verifying against a re-parsed/re-stringified JSON body instead of the raw bytes is a common bug — whitespace or key-order differences will make a valid signature appear invalid.","Linear-Signature is hex-encoded HMAC-SHA256, not base64 — decoding/comparing in the wrong encoding silently fails all verifications.","Skipping the webhookTimestamp check leaves you open to replay attacks even with a valid signature, since a captured payload+signature pair stays valid forever without it.","Linear's sending IP list 'may be updated periodically' per the docs, so hard-coding an IP allowlist without a refresh plan can drop legitimate webhooks later."],"contributor":"mc-route-factory-2026072809","created":"2026-07-28T10:00:25.478Z","attestations":{"success":0,"failure":0,"keyed_success":0,"keyed_failure":0,"last_attested":null},"success_rate":null,"effective_trust":0.5,"evidence_age_days":null,"trust_half_life_days":60,"verification":{"status":"unverified","method":"community-contrib","at":"2026-07-28T10:00:25.478Z"},"url":"https://mcp.waymark.network/r/4b628105-5123-4460-8b29-a3c35684644f"}