Skip to content

Slack HTTP mode fails — url_verification challenge rejected due to missing signature #39432

@angelor888

Description

@angelor888

Bug type

Regression (worked before, now fails)

Summary

When channels.slack.mode is set to http, OpenClaw cannot complete the Slack url_verification handshake because Slack sends this initial challenge without a signature, but OpenClaw rejects unsigned requests, making HTTP mode permanently non-functional.

Steps to reproduce

  1. Set channels.slack.mode: "http" in openclaw.json and configure signingSecret
  2. In Slack App settings, under Event Subscriptions, enter your webhook URL (e.g. via ngrok)
  3. Slack sends a POST to the webhook URL with {"type": "url_verification", "challenge": "..."}
  4. This request has no X-Slack-Signature header (Slack does not sign the initial challenge)
  5. OpenClaw either rejects it or fails to respond with the challenge value
  6. Slack marks the URL as invalid — HTTP mode never activates
  7. Gateway logs show the config change was accepted (config hot reload applied) but the handshake never completes

Expected behavior

OpenClaw responds to Slack's url_verification challenge with the {"challenge": "..."} value, completing the handshake and activating HTTP webhook mode.

This is consistent with how Slack's own official SDKs (bolt-js, python-slack-sdk) handle it — they explicitly whitelist url_verification from HMAC signature checks, since Slack does not sign this one request type by design.

Actual behavior

Slack rejects the webhook URL as invalid. HTTP mode never activates. OpenClaw silently falls back to or remains in Socket Mode with no error surfaced to the user.

OpenClaw version

2026.3.2

Operating system

macOS Darwin 25.3.0 arm64

Install method

npm global (node v25.6.1)

Logs, screenshots, and evidence

Gateway log showing config accepted but handshake never completing:

[INFO] config hot reload applied (channels.slack.mode)
[INFO] slack socket mode listening at /slack/events

No subsequent log entry from Slack confirming the url_verification challenge was answered. Slack Event Subscriptions UI shows the URL as unverified/failed.

Impact and severity

Affected: Any user trying to use Slack HTTP webhook mode (Events API) instead of Socket Mode
Severity: High — HTTP mode is completely non-functional; blocks a critical stability improvement
Frequency: 100% reproducible — Slack always sends url_verification unsigned by design
Consequence: Users are forced to use Socket Mode, which has periodic WebSocket drops (every ~90 min via the internal health-monitor stale-socket restarts). Messages sent during reconnect windows (~1–2 sec) are silently lost. HTTP mode would eliminate this entirely — no persistent connection, no drops, no lost messages.

Additional information

Workaround in place: Socket Mode + custom watchdog script (com.sky.slack-watchdog launchd agent) that detects pong timeouts and restarts the gateway within 2 minutes. This reduces max downtime but does not eliminate dropped messages.

Root cause reference: Slack's own documentation states url_verification is intentionally sent unsigned: https://api.slack.com/events/url_verification

Bolt.js source for comparison (skips signature check for url_verification): https://github.com/slackapi/bolt-js/blob/main/src/receivers/ExpressReceiver.ts

Suggested fix: In the HTTP webhook handler, check if req.body.type === 'url_verification' before running signature verification. If so, respond immediately with {"challenge": req.body.challenge} and skip the HMAC check for this one event type only.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingregressionBehavior that previously worked and now fails

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions