A URL that is actually a password
Slack and Discord both let you send messages into a channel by POSTing to a webhook URL. The whole design is that it is simple — no auth header, no token exchange, just the URL. That is exactly the problem. The URL is the credential. Whoever holds the full link can post into your channel, and the platform has no way to tell them apart from your own app.
Because it looks like an ordinary link, people treat it like one. That is how it leaks.
What someone can do with a leaked one
It is not catastrophic the way a leaked database password is, but it is not nothing:
- Post anything into your channel — spam, abuse, or links your team trusts because they appear in an internal channel.
- Phish your own staff. A message that lands in
#alertsor#deployslooks legitimate, which makes a fake 'click to approve' far more convincing. - Drown out real signals. If the channel is for monitoring or error alerts, a flood of junk can bury the messages that matter.
The channel is internal and trusted, and that trust is precisely what an attacker borrows.
Where these URLs leak
The pattern is the same one that catches API keys:
- In the frontend bundle. A 'notify us on signup' feature wired straight into client code ships the webhook URL to every visitor.
- Committed to a repo. Pasted into a config file or a script, then the repo goes public or gets forked.
- In CI logs and error traces. A failed request that prints the full URL into a build log or a Sentry event.
- In docs and tickets. Dropped into a README or a support ticket for convenience, then forgotten.
Webhook URLs have a recognizable shape — hooks.slack.com/services/... or discord.com/api/webhooks/... — so automated scanners spot them quickly once they are public.
How to handle them safely
- Keep the call server-side. The browser should hit your own endpoint; only your server holds the webhook URL.
- Store it as a secret, in environment configuration or a secrets manager — never hardcoded in code that ships.
- Rotate anything exposed. Both platforms let you delete and reissue a webhook in seconds. If a URL was ever public, regenerate it and update your config.
- Scope the channel. Point webhooks at a dedicated, low-stakes channel rather than one where a fake message could trigger an action.
Check what your site exposes
The awkward part is that a webhook URL hidden in a large bundle is invisible to the eye. An automated scan reads your pages and scripts the way a bot would and flags webhook URLs that are reachable from the browser — scan your site and find out before someone posts in your channel for you.