Run your webhook endpoint through a security header scanner and you might get a clean report: HSTS present, correct content-type options, a reasonable content security policy. It's genuinely good to have those headers configured correctly. It's also completely orthogonal to whether your endpoint actually verifies who's sending it data, which is a different layer of security entirely, and the one that matters most for a webhook specifically.

Photo by Brett Sayles on Pexels
Two Different Questions, Two Different Layers
Security headers answer questions like: can this response be embedded in an iframe on another site? Will the browser enforce HTTPS on future requests? Is content sniffing disabled? These are all about how a browser should treat responses from your server, protecting the people visiting your site in a browser.
A webhook endpoint doesn't serve browsers. It receives server-to-server POST requests from a service like a payment processor or a source control platform, and nothing about response headers has any bearing on whether an incoming request is legitimate. The header grade tells you your server is well-configured for browser-facing traffic. It tells you nothing about whether an attacker who finds your webhook URL can successfully send it a forged payload.
What Actually Protects a Webhook Endpoint
The layer that matters for webhooks is request authentication, specifically, verifying an HMAC signature attached to the incoming payload, computed using a secret key shared only between you and the sending service. No security header accomplishes this. A perfectly configured Content-Security-Policy does nothing to stop someone from POSTing a fake "payment.succeeded" event straight to your endpoint if there's no signature check on the receiving end.
This is a genuinely easy mistake to make, because both things get lumped together under "web security" in a lot of general checklists, and running a scanner that returns a passing grade feels like it should mean the endpoint is covered. It means something real, just not the thing a webhook endpoint most needs. The confusion usually comes from treating "security" as one undifferentiated category rather than several distinct layers that each protect against a different kind of attack.
A Reasonable Security Posture for a Webhook Endpoint
A properly secured webhook receiver needs several layers doing their actual jobs, not one substituting for another:
Transport layer: HTTPS enforced, ideally with HSTS, so the payload can't be intercepted or tampered with in transit at the network level. This is the layer a security header scanner is actually built to check, and it's a real, necessary layer, just not a sufficient one on its own.
Authentication layer: HMAC signature verification on every incoming request, using a constant-time comparison, checked against a secret key that's rotated if it's ever exposed. This is the layer that actually answers "did this request come from who it claims to be from."
Application layer: Idempotency handling so a duplicate delivery, which most webhook providers guarantee will eventually happen under normal retry behavior, doesn't process the same event twice, and reasonable input validation on the payload itself, since a valid signature only proves origin, not that the payload is well-formed or safe to act on blindly.
A scanner covers roughly the first item on that list and none of the other two. That's not a knock on header scanners, they're doing exactly what they're built to do, it's just a reminder that "passed the scan" and "the endpoint is actually secure" aren't the same claim, and treating them as equivalent is where the real risk creeps in.
A Real Insight From Watching Teams Get This Wrong
I've watched teams spend a sprint chasing an A+ security header grade on an endpoint that had no signature verification at all. The grade felt like progress, and in a narrow sense it was, every header fixed is a header fixed. It just wasn't addressing the actual attack surface a webhook endpoint presents, which is an unauthenticated POST route sitting on the open internet. Fix the layer that matches the actual threat model first, then worry about the polish on top of it.
How This Shows Up in a Real Incident
The way this gap actually gets discovered, in practice, is rarely a planned security review. It's usually a support ticket about a duplicate order, a refund that shouldn't have processed, or an account change nobody on the team actually made, followed by an investigation that eventually traces back to an endpoint accepting requests from anyone who knew the URL. At that point, the team pulls up the security scan history and finds a clean, passing grade the whole time, which is exactly the confusing part: every tool they checked said things were fine, because every tool they checked was answering a different question than the one that actually mattered.
That's the practical argument for treating header grades and signature verification as two separate line items on a security checklist rather than one combined "is this endpoint secure" checkbox. A team that explicitly tracks both is far less likely to end up in the situation above than one that treats a passing scanner result as the finish line.
Checking Your Own Headers Without Assuming They Cover Everything
Running a header check is still worth doing, just with the right expectations attached. EvvyTools' HTTP Security Header Grader scans a URL and reports back which standard security headers are present, missing, or misconfigured, which is genuinely useful for the transport and browser-facing layer of your stack. Treat a clean result there as one item checked off a longer list, not confirmation that a webhook receiver behind that same domain is authenticating its incoming requests correctly.
Where the Real Gap Usually Gets Closed
If your header scan comes back clean and you haven't separately confirmed your webhook handler verifies an HMAC signature and rejects tampered payloads, that's the actual gap worth closing next. Why Webhook Signature Verification Uses HMAC Instead of a Plain Hash covers what that verification step actually needs to do and why a simpler checksum comparison doesn't get you there. Reading both pieces together gives a more complete picture than either one alone, since they're describing two different, complementary layers rather than two versions of the same advice.
Building a Checklist That Covers Both Layers
If you're setting up a review process for new endpoints, it's worth building a single checklist that explicitly separates these two categories rather than one flat list that implicitly conflates them. Something like: transport and browser-facing headers (HSTS, content-type options, frame options, content security policy) in one section, and authentication and correctness checks (signature verification, constant-time comparison, timestamp validation, idempotency handling) in a separate section. Reviewing a new webhook endpoint against both sections explicitly, rather than a single merged checklist, makes it much harder to walk away with a false sense of completeness after only covering one of the two.
For general security header reference, MDN's HTTP headers documentation covers what each header does and when it's appropriate. OWASP maintains broader secure headers and API security guidance worth reading alongside a header scan result, and the Mozilla project popularized a lot of the header-grading approach these scanners are modeled on, if you want more background on where the practice came from and why headers became a standard checklist item in the first place. EvvyTools has a growing set of free developer tools beyond the header grader referenced here, worth a look if you're building out a broader endpoint review checklist.
Top comments (0)