ImpulseyeImpulseye
FeaturesIntegrationsPricingBlogChangelogIs It Down?
All posts
Security

Why a plain webhook URL field is a security boundary

Any feature that lets a user tell your server to make an HTTP request to a URL of their choosing is a server-side request forgery surface — even if it looks like an innocent settings field. Here's how I hardened mine.

June 21, 2026 4 min read

Impulseye lets you add a channel and paste in a webhook URL — Discord, Slack, Teams, a generic endpoint of your own. That single text field is also, by definition, a place where a user can ask my server to make an HTTP request to anywhere they want. That's server-side request forgery (SSRF), and it's worth treating seriously even in a small product.

Why it matters

The threat isn't "a user sends themselves a webhook." It's that your server — sitting inside your own private network, often with access other requests don't have — is the one making the request. A malicious value in that field isn't asking your server to fetch a website; it's asking your server to reach into places an outside attacker normally couldn't reach directly: internal admin panels, cloud metadata endpoints, services on localhost, or anything else reachable from inside your infrastructure but not from the public internet.

The general shape of the risk

Any server-side code path that accepts a user-supplied URL and then fetches it — webhooks, image proxies, "import from URL" features, link previews — inherits this risk by default. It's not specific to alerting tools. If your server fetches a URL a user gave it, this applies to you too.

The fix

This is well-trodden ground — OWASP has a dedicated SSRF prevention cheat sheet, and the shape of a real fix is consistent across implementations:

  • Validate the destination, not just the format. A URL can be syntactically perfect and still resolve to an internal or reserved address. Checking "is this a valid URL" is not the same as checking "is this a safe destination."
  • Resolve before you trust. A hostname's DNS resolution can point somewhere different at request time than it did at validation time. The address actually being connected to is what needs checking, not just the hostname string.
  • Don't trust redirects blindly. A URL can validate cleanly and then redirect somewhere unsafe. Following redirects without re-validating the new destination reopens the same hole one hop later.
  • Apply it at every entry point, not just the obvious one. If a URL can be set on creation, it can usually also be changed later through a different code path — an edit endpoint, a test button, a background job that re-reads stored settings. Every one of those needs the same validation, not just the first form a user sees.

None of this is exotic. It's the standard, published mitigation for a well-known bug class — which is exactly why there's no excuse for skipping it just because the feature looks as harmless as "paste your webhook URL here."

Hardest part

Writing the validation function wasn't the hard part. Finding every place a URL could enter the system was. A webhook URL can be set when a channel is created, changed when it's edited, and re-read whenever an alert actually fires — three separate code paths, only one of which is the obvious "add channel" form a security review would naturally focus on first. A guard on the creation endpoint alone would have left the other two wide open.

The actual takeaway: treating "where can this value be set" as a single question with one answer is the mistake. Any value that matters for security needs the same check applied everywhere it can enter or re-enter the system — not just at the entry point that's easiest to remember to guard.

Back to all posts
Share

Monitor your sites with Impulseye

Uptime checks, SSL warnings, and alerts across 9 channels.

Start free

Keep reading

Engineering 5 min

I built myself a tiny ops dashboard. It found 30 real problems in five minutes.

A personal, owner-only page to stop bouncing between the Hetzner, Supabase, and Resend consoles by hand — and it immediately surfaced a stack of real database performance issues I didn't know I had.

July 19, 2026Read
Infrastructure 7 min

My load test was lying to me, and I almost believed it

Before renting a real server, I built a load-testing rig to find Impulseye's actual ceiling. It reported a ceiling that didn't exist — the test harness itself had two bugs, and both of them looked exactly like a capacity problem.

July 14, 2026Read
Postmortem 6 min

The signup bug that almost shipped on launch day

A single trigger wired to the wrong table meant every new signup would have failed — and every digest email would have silently gone nowhere. Here's how I found it before opening the doors.

July 2, 2026Read
ImpulseyeImpulseye

Uptime monitoring that is dead simple. Instant alerts via email, Slack, and Discord, set up in under 30 seconds.

support@impulseye.com

Product

  • Features
  • Integrations
  • Pricing
  • Blog
  • Changelog

Tools

  • Is It Down?
  • Dashboard
  • Status Pages
  • Impulseye Status
  • API Docs
  • FAQ

Legal

  • Terms of Service
  • Privacy Policy
  • Refund Policy

© 2026 Impulseye. All rights reserved.

ContactTermsPrivacy