10 Webhook Providers That Don't Sign Their Payloads (And What to Do)
Not every provider signs webhooks. When the provider hands you an unauthenticated POST, you have to invent your own security model. Here are the providers, the reasons, and three patterns that work.
The Awkward Reality
You'd assume in 2026 every webhook provider signs their payloads. They don't. Some legacy systems, internal tools, and even a few well-known SaaS products will happily POST unsigned JSON to whatever URL you give them.
If you wire that endpoint up naively, anyone on the internet who guesses the URL can post arbitrary events into your system. Order created. User upgraded. Payment refunded. The receiver has no way to tell.
Common Offenders
This list is current as of April 2026 — providers do upgrade their signing over time, so verify against current docs.
- Older Jira on-prem instances — webhook events arrive unsigned by default; signing requires a separate plugin
- Many internal CI tools — Jenkins, TeamCity, custom build pipelines often POST plain JSON
- IoT device manufacturers — most consumer-grade devices send to a fixed URL with no auth
- Legacy CRMs — several mid-tier CRMs from the 2010s still don't sign
- Custom in-house webhook senders — built once, never updated
- Some self-hosted tools (Gitea, older Gitlab versions) — secrets are optional and frequently not configured
- Form builders — many "send to webhook" form tools post unsigned
- Survey platforms — same pattern as form builders
- A surprising number of analytics platforms — they assume the webhook URL itself is secret
- Legacy ERP integrations — typically delivered unsigned over a VPN
The common thread: each of these treats the URL itself as the secret. That's only safe if the URL has enough entropy and never leaks — which it always does.
Pattern 1: Shared Secret in the URL
The simplest fix. Generate a long random string and include it in the URL path or query:
https://api.example.com/webhook/8e3a7f2c91d4b5a6...
Verify the secret on every request. Reject anything that doesn't match.
Pros: Works with any provider that takes a URL. Zero changes on the sender side.
Cons: The secret leaks anywhere the URL appears — server logs, browser history (if accidentally pasted), referrer headers, error messages. Treat it as moderately secret, not very secret.
Pattern 2: IP Allowlist
If the provider publishes a stable set of source IPs, only accept connections from those IPs:
const ALLOWED = ['198.51.100.0/24', '203.0.113.42'];
function isAllowed(ip: string) {
return ALLOWED.some(cidr => ipInCidr(ip, cidr));
}
Pros: Very strong if the provider's IP list is reliable.
Cons: Most providers don't publish IPs. Those that do change them occasionally without warning. Doesn't work if you're behind a CDN or load balancer that masks the source IP.
Pattern 3: Bolt Signing on at the Edge
Put a layer in front of the unsigned webhook that turns it into a signed one. The unsigned URL is internal-only; nothing reaches your real handler without a signature.
This is exactly what Hookbase does. The public URL accepts the unsigned payload, generates an HMAC, and forwards it to your handler with a proper X-Hookbase-Signature header. Your handler only ever sees signed traffic, even from providers that don't sign.
You can also use the URL-secret pattern (#1) on the inbound side to gate the public URL itself. Combined: a secret-in-URL stops most random scanners, and signed forwarding gives your handler a reliable trust boundary.
What Not to Do
Don't trust the provider's claim that "the URL is the secret." URLs leak. Always.
Don't use HTTP Basic Auth in the URL (https://user:pass@...). Many HTTP clients strip credentials from URLs, and the credentials end up in logs anyway.
Don't rely on User-Agent strings for verification. They're trivially spoofed.
Don't accept the payload first and verify later. If your handler does any work — even logging — before checking authenticity, an attacker can flood your queue with junk that passes initial parsing.
Bonus: Check What You Think Is Signed Actually Is
Several providers say they support signing but only enable it if you flip a checkbox or set a secret. Defaults vary:
- Gitea: signing optional, must set secret
- Older self-hosted Gitlab: same
- Mattermost outgoing webhooks: optional token, not HMAC
- Some Zapier-style integrators: depend on the source app
When you wire up a new webhook, send yourself a test payload and confirm there's a signature header before you start trusting the data.
How Hookbase Helps
Hookbase normalizes this mess. Whether the provider signs or not, your handler always receives a Hookbase-signed event. We add a verification layer on top of providers that don't have one, and we verify on your behalf for the 30+ providers that do. One signature scheme, one verification path, every provider.