Skip to main content
Glama
Larslllllll

webhook-verify

by Larslllllll

webhook-verify

Timing-safe, replay-resistant webhook signature verification for Stripe, GitHub, Slack, Shopify and Twilio.

29 passed

Standard library only. No dependencies, no network, no telemetry.

Why

Webhook verification is the one piece of security code almost every backend writes itself, and it goes wrong in four predictable ways:

Mistake

Consequence

signature == expected

Byte-by-byte comparison leaks the position of the first wrong byte through timing. Forgeable given enough attempts.

No timestamp check

A captured valid request stays valid forever. Replay it tomorrow and it still passes.

Verifying the parsed body

You re-serialise, a key order or whitespace changes, and the HMAC no longer matches — so people "fix" it by skipping verification.

Returning False on failure

A caller writes if verify(...) and a truthy string or None slips through.

This library does the opposite of each: hmac.compare_digest everywhere, replay windows on every provider that signs a timestamp, verification against the raw body, and a specific exception on every failure so nothing can be accidentally treated as success.

Use

from webhookverify import verify_stripe, SignatureMismatch, TimestampOutOfRange

try:
    verify_stripe(secret, raw_body, request.headers["Stripe-Signature"])
except TimestampOutOfRange:
    return 400, "replayed or clock-skewed"
except SignatureMismatch:
    return 401, "not from Stripe"
# only now is it safe to parse raw_body

Supported: verify_stripe, verify_github, verify_slack, verify_shopify, verify_twilio, and verify_hmac for anything else.

Stripe secret rotation is handled: a header carrying several v1= signatures passes if any one matches.

MCP server

mcp/server.py exposes one tool, verify_webhook, over JSON-RPC 2.0 stdio (protocol 2024-11-05). It returns valid:true, or valid:false with a precise reason (signature_mismatch, timestamp_out_of_range, malformed_signature) and the instruction not to parse the payload.

{ "mcpServers": { "webhook-verify": { "command": "python3", "args": ["/path/to/webhook-verify/mcp/server.py"] } } }

Tested behaviour

  • Valid signatures pass for all five providers

  • Tampered bodies, wrong secrets and truncated signatures raise SignatureMismatch

  • Replayed and future-dated timestamps raise TimestampOutOfRange (the window is symmetric)

  • Malformed headers raise MalformedSignature — missing prefix, bad base64, non-hex, non-numeric timestamp

  • Stripe multi-v1 rotation passes when any signature matches

  • A source-level guard asserts the module never regresses to == on digests and always length-checks before compare_digest

python -m pytest tests -q

License

MIT

-
license - not tested
Not graded
quality - not tested
C
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

  • A webhook inbox for agents: one call returns a live URL. Mock, verify, inspect and replay.

  • Verify PyPI and npm packages, symbols, and version diffs against real artifacts. Free, no account.

  • Turn inbound email into a webhook — verify, parse, route, and store incoming messages.

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Larslllllll/webhook-verify'

If you have feedback or need assistance with the MCP directory API, please join our Discord server