Safeguard
Vulnerability Analysis

SSRF via webhooks explained

Webhook SSRF turns a trusted callback feature into an internal network foothold. Here is how the attack works, real incidents, and how to actually fix it.

Yukti Singhal
Security Researcher
7 min read

A webhook is a URL your application will fetch, POST to, or fetch from, on someone else's say-so, and that is precisely what makes it a server-side request forgery vector. Webhook SSRF happens when an attacker supplies or manipulates the destination URL in a webhook registration, delivery, or retry flow, causing the server to issue requests to internal infrastructure instead of the intended external endpoint. Slack's 2017 webhook SSRF, GitHub's 2019 webhook redirect bug, and the pattern behind Capital One's 2019 breach (over 100 million records, via SSRF into AWS metadata) all trace back to the same root cause: a server-side HTTP client that trusted a URL it should have validated. Because webhooks are a first-class integration primitive in CI/CD platforms, SaaS tools, and internal automation, the blast radius runs from cloud credential theft to internal port scanning to full remote code execution. This post explains how webhook SSRF works, where it hides in real systems, and what stops it.

What Is Webhook SSRF?

Webhook SSRF is server-side request forgery that specifically abuses the webhook delivery or registration path rather than a generic user-input field. In a normal webhook flow, a user registers a callback URL (for example https://customer.example.com/hooks/incoming), and the server later sends an HTTP request to that URL when an event fires -- a deployment completes, a payment posts, an issue is closed. The vulnerability appears when the server does not restrict what that URL can point to. An attacker registers http://169.254.169.254/latest/meta-data/iam/security-credentials/ or http://localhost:8080/admin as the "webhook URL," and the server, acting as a fully trusted internal client, fetches it and often returns the response body back to the attacker through delivery logs, retry payloads, or error messages. The webhook subsystem becomes a blind SSRF-to-read primitive with almost no additional exploitation needed. This differs from classic SSRF in file-upload-preview or PDF-generation code paths mainly in persistence: a webhook URL is stored, retried on a schedule, and re-triggered by every subsequent event, giving the attacker repeated, low-noise access rather than a single request.

Why Do Webhooks Create Such a Direct Path To Internal Infrastructure?

Webhooks create a direct path to internal infrastructure because the server that sends the callback almost always runs inside the trusted network perimeter, with access to resources external attackers cannot reach directly. A webhook dispatcher typically runs as a backend service or worker process with network reachability to the cloud metadata endpoint (169.254.169.254 on AWS, GCP, and Azure), internal APIs on RFC 1918 address space, service meshes with no additional auth for east-west traffic, and sometimes the orchestration control plane itself. The Capital One breach in 2019 is the reference case: an SSRF vulnerability in a misconfigured WAF let an attacker reach the AWS IMDSv1 metadata service, retrieve temporary IAM credentials for a role with S3 read access, and exfiltrate data belonging to more than 100 million customers. The webhook variant is functionally identical -- swap "WAF request forwarding" for "webhook delivery" and the exploitation mechanics do not change. What makes webhooks worse as an SSRF vector specifically is that the URL is user-supplied by design (that is the entire point of a webhook), so there is no obviously "wrong" input to flag; the server is doing exactly what it was built to do, just against the wrong target.

Which Real-World Incidents Show This Pattern?

At least three widely documented incidents show the webhook/callback-URL SSRF pattern causing material impact. Microsoft's Exchange ProxyLogon chain (CVE-2021-26855, disclosed March 2021) used an SSRF in the Exchange Client Access Service to forge a trusted internal request, which was chained with an authentication bypass to compromise tens of thousands of Exchange servers globally within days of disclosure. GitHub's webhook subsystem was reported in 2019 to be vulnerable to SSRF via redirect: a webhook URL that returned an HTTP 3xx to an internal address could cause GitHub's delivery worker to follow the redirect and issue a request server-side, a bug class GitHub subsequently hardened by re-validating the destination after every redirect hop. Atlassian's Confluence Server SSRF (CVE-2023-22527, January 2024) combined a template-injection primitive with SSRF to reach internal endpoints and was scored CVSS 9.8, with mass exploitation observed within a week of a public proof-of-concept. Slack, Discord, and Stripe have all published webhook-URL validation requirements in their integration documentation specifically because unvalidated callback registration is the most common way third-party developers reintroduce this bug in their own systems.

What Makes Webhook SSRF Harder To Block Than Ordinary SSRF?

Webhook SSRF is harder to block than ordinary SSRF because standard mitigations -- DNS resolution checks, IP allowlists, protocol restrictions -- all have to hold not just at registration time but at every single delivery, including retries that can happen hours or days later. A URL that resolves to a public IP when a user registers it can be repointed to 127.0.0.1 via DNS rebinding before the next scheduled retry; the TTL on the DNS record is entirely attacker-controlled. A validation check that runs only at webhook-creation time and never again is a textbook time-of-check/time-of-use gap. Redirects compound the problem: a webhook that validates the initial destination but blindly follows a 302 to http://169.254.169.254/ has validated nothing. Protocol confusion is a third gap -- allowlisting http:// and https:// looks safe until a library also honors file://, gopher://, or dict:// schemes, each of which has been used in real SSRF exploit chains (notably gopher:// in Redis and Memcached SSRF-to-RCE exploits). A 2023 review of webhook implementations across popular SaaS platforms found that fewer than half re-validated the resolved IP address on every delivery attempt rather than only at initial registration, which is the specific gap DNS rebinding exploits.

How Do You Actually Fix Webhook SSRF?

Fixing webhook SSRF requires validating the destination on every outbound request, not just at registration, using resolved-IP allowlisting rather than hostname string matching. Concretely: resolve the DNS name to an IP address immediately before connecting, reject private (RFC 1918), loopback (127.0.0.0/8), link-local (169.254.0.0/16, which includes every major cloud's metadata endpoint), and multicast ranges at that resolved IP, and re-run the same check after following any redirect rather than trusting the original validation. Disable protocol schemes other than http and https in the HTTP client used for delivery -- most SSRF-to-RCE chains involving Redis, Memcached, and internal RPC services depend on gopher:// or similar scheme abuse that a plain URL-string allowlist misses. Route all webhook egress through a dedicated proxy or network policy that enforces the same IP-range denylist at the network layer as a second, independent control, so an application-layer bypass does not translate directly into network access. Finally, treat DNS resolution as a race condition: pin the connection to the specific IP you validated (do not re-resolve between the check and the connect) to close the rebinding window. IMDSv2 with hop-limit set to 1 on AWS, and equivalent metadata-service hardening on GCP and Azure, is a compensating control that limits blast radius even if an SSRF slips through the application layer.

How Safeguard Helps

Safeguard identifies webhook-handling code paths that construct outbound HTTP requests from user-controlled URL parameters and flags them for SSRF review as part of its SAST and reachability analysis, distinguishing exploitable sinks from validated ones instead of flagging every http.get() call in the codebase. Griffin AI traces the data flow from webhook registration input to the outbound request call, confirms whether an IP or protocol allowlist actually sits on the path a request will take (including after redirects), and generates an auto-fix PR that adds resolved-IP validation and pins the connection to prevent DNS rebinding. Because webhook SSRF often lives in third-party libraries and internal frameworks rather than first-party code, Safeguard's SBOM ingestion cross-references known SSRF advisories against the exact dependency versions in use, so a vulnerable webhook-delivery library is caught even when your own integration code looks clean. The result is a prioritized, reachability-confirmed list of webhook SSRF exposure -- with a proposed fix -- instead of a generic SSRF checklist your team has to manually verify against production code.

Never miss an update

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