Safeguard
Developer Tools•

How do you verify that a request really came from Slack?

Check the X-Slack-Signature header with your signing secret over the raw body, and reject requests older than five minutes to block replays.

Safeguard Security Team
4 min read

Compute an HMAC SHA-256 over the version, the request timestamp and the raw body using your app's signing secret, then compare it to the X-Slack-Signature header. Reject any request whose timestamp is more than five minutes from your clock. Do this before parsing or acting on the payload.

Why the signature matters

Your Slack app exposes a public URL. Anyone can send it a POST that looks like a Slack event or a slash command. Without verification, a stranger can make your app post messages, call internal systems, or leak data. The signing secret is how Slack proves a request is genuine.

Slack's documentation describes the scheme. On each HTTP request Slack adds an X-Slack-Signature header, created by hashing the request body with SHA-256 combined with an HMAC signing secret. Because the signature depends on the timestamp, it also helps against replay. Signing secrets replace the older verification tokens.

The steps

  1. Read the raw body. Do this before any JSON or form parsing. In some frameworks you must call the raw read method first, because re-serializing changes the bytes.
  2. Read the timestamp header, X-Slack-Request-Timestamp.
  3. Check freshness. If the absolute difference between your clock and the timestamp is more than five minutes, ignore the request. The documentation's own example uses 300 seconds.
  4. Build the base string. Concatenate the version, the timestamp and the raw body with a colon between each part. The version in the documented example is v0.
  5. Compute the HMAC. Hash the base string with your signing secret and prefix the hex digest with the version.
  6. Compare in constant time to the header value. If they differ, return an error and stop.

Official SDKs can do this for you. Use them where possible, since a hand rolled comparison is an easy place to slip.

Common mistakes

MistakeEffect
Parsing JSON before reading the bodySignature never matches
Skipping the timestamp checkCaptured requests can be replayed
Using a normal string equality checkLeaks timing information
Logging the signing secret while debuggingThe secret ends up in logs
Keeping the old verification token as a fallbackWeaker path stays open

Where to keep the signing secret

In your secrets store, not in code or a chat message. Rotate it if it may have been exposed. The first part of that is covered in how to rotate leaked API keys. A signing secret is a shared secret, so anyone who holds it can forge valid requests.

Respond fast too

Slack expects a 2xx within three seconds for events, so verify, acknowledge and queue. The reasoning is in why a webhook endpoint should answer in seconds.

Try it yourself

Click through it at your own pace, or open it full screen. Look at how endpoints without authentication checks get flagged.

Where Safeguard fits

Safeguard's API security scanning and dependency scanning can help you find unauthenticated routes and vulnerable libraries in an integration like this. A free scan is a way to start.

Quick check

Is the five minute window required?

It is what Slack's documented example uses to limit replays. Pick a window no wider than that.

Do I still need to verify if the URL is secret?

Yes. A URL can leak through logs, proxies or screenshots. The signature is the control.

Sources

Last reviewed: 19 October 2026.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.