Home/ Blog/ Deep dive/ Article
Signal · Weekly Analysis

Four SSRF flaws in one week turned self-hosted apps into a foothold in your own network

Four unrelated products shipped SSRF flaws this week, from a Kubernetes proxy to MLflow. Why self-hosted SSRF reaches cloud metadata, and how to contain it.

Outbound request curving back inside a server room toward a vault of cloud keys

Four different products shipped a server-side request forgery flaw this week. One was a Kubernetes control plane. One was a WordPress email plugin. One was a URL parser buried in the dependency tree of countless Node.js apps. One was a machine-learning tracking server. They share no vendor, no language, and no user base. They reached our desk inside seven days doing exactly the same thing: taking a request the application was built to make, and pointing it somewhere it was never meant to go.

SSRF was the sixth most common bug class our threat desk triaged this week, with 99 logged decisions among the 5,112 vulnerabilities that reached a recorded verdict. That ranking undersells it. Command injection and cross-site scripting sit higher by raw count, but they are loud and well understood. SSRF is the quiet one, usually rated somewhere in the middle, easy to wave off as a web bug. This week's four make the case that it is the bug class most likely to turn a single exposed app into a foothold inside the network you assumed it was sitting behind.

SSRF: an outbound feature turned into inbound access
  1. 1Attacker reaches a public route, or hands the app a URL to fetch
  2. 2The app makes the outbound request on the attacker's behalf
  3. 3A name-based allowlist passes; the address is re-resolved or re-decoded
  4. 4The request lands on cloud metadata (169.254.169.254) or an internal serviceDetection point
  5. 5Instance credentials or internal data return to the attacker
The same five steps recur across this week's four SSRF flaws. A defender's clearest catch is the egress the app server should never make.

Four products, four layers, one request

Start with the worst of them. Red Hat's Multicluster Engine for Kubernetes carries CVE-2026-66794, a critical flaw in its cluster-proxy add-on. An unauthenticated attacker who can reach the add-on's public route can relay traffic to the internal services running on any cluster the hub manages. The component's whole job is to tunnel from a hub to the clusters it governs, so an exposed route hands a stranger the inside of every cluster behind it. There is no fixed build yet; the only guidance is to restrict who can reach the route.

Now the mundane end. The Mailgun for WordPress plugin (CVE-2026-78003, rated critical by Wordfence) lets an unauthenticated visitor abuse the plugin's own outbound mail path to reroute a site's email and seize the administrator account. Same primitive, humbler host: an app that legitimately reaches out to a mail service is talked into reaching somewhere else, using credentials it already holds.

Then the dependency nobody chose directly. fast-uri (CVE-2026-75899) is the URL parser inside Fastify and a long list of other Node.js projects, usually pulled in as a transitive dependency you never named. It decodes a hostname twice, so a double-encoded address slips past an allowlist check and then resolves to localhost or a cloud metadata endpoint. The bug is not in your code; it is three levels down in your lockfile.

And the one already being exploited. MLflow's webhook delivery (CVE-2026-64849) validates that a webhook hostname is public, discards the address, then re-resolves the name at delivery time. A DNS-rebinding trick points that second lookup at 169.254.169.254, and MLflow's test path hands back whatever that address replied with, which on a cloud host is the instance role's live credentials. CISA added it to the Known Exploited Vulnerabilities catalog on August 19 with a federal patch deadline of September 2. Of the roughly 74 vulnerabilities we flagged as exploited or likely to be this week, this is the SSRF one.

The check that is not a control

Look at how two of these actually fail and the pattern stops being a coincidence. MLflow checks a hostname, then resolves it again later; fast-uri decodes a hostname, then decodes it again later. In both, the value that passed validation is not the value that gets used. The allowlist inspects a label, the socket connects to a destination, and nothing guarantees the two agree.

That gap is the heart of SSRF, and it is why the bug class resists a single fix. An allowlist on a hostname string is a check on how an address looks, not on where the packet goes. Attackers keep a deep bag of tricks for making those two disagree: double encoding, DNS rebinding, redirects, decimal or IPv6 notation, a trailing dot. Every one of them works the same seam between the name we approved and the address we dialed. MLflow's fix is instructive precisely because it stops trusting the name at all. The patched build validates the peer IP of the socket it actually connected to, moving the check to the one place that cannot be spoofed after the fact.

Why self-hosted software keeps handing this out

Here is the part a newsroom covering each CVE on its own will miss. An SSRF flaw is only as dangerous as what the vulnerable server can reach, and self-hosted software runs inside your walls, next to everything worth reaching. The metadata endpoint at 169.254.169.254 that hands out cloud credentials. The internal admin ports bound to loopback. The other services on the cluster. The neighboring app left unauthenticated because it is only on the internal network. None of those are reachable from the internet. All of them are reachable from your own application server, which is exactly the machine an attacker just borrowed.

That is the exposure translation self-hosting owes you. When you run the app, you also own its position in the network, and SSRF converts that position into the attacker's. The cloud-metadata pivot is the sharpest example because the payoff is durable. Truffle Security reported this month that 88 percent of the leaked AWS keys it re-verified still authenticated, and hundreds carried full administrative rights, so a stolen instance credential is not a momentary problem. An SSRF that reaches metadata is, for practical purposes, credential theft with a long tail.

What actually contains SSRF

You cannot patch a bug class, and four flaws in four unrelated products in one week is the reminder. Next week it will be a fifth product you also run. What contains SSRF is not any specific CVE fix but the architecture around your application's outbound traffic, and most of it you can put in place without waiting on a vendor.

Treat egress as something to control, not just ingress. An application server usually has a short, boring list of places it genuinely needs to reach; everything else is a candidate to block by default. For the services you run on a cloud host, block outbound access from app servers to 169.254.169.254 outright, and enforce IMDSv2 with a metadata hop limit of 1 so a rebinding request cannot complete the token handshake even if it lands. Where you make outbound requests from user-supplied URLs, validate the resolved IP at the moment of connection, the way MLflow's patched build does, rather than trusting a name you checked earlier. And assume the credential behind any metadata pivot will outlive the incident: short-lived credentials from role assumption or federation expire on their own, which turns a stolen key from a standing liability into a brief one.

Then there is the question a patch never answers: how would you know? Upgrading MLflow or fast-uri closes a hole. It does not tell you whether someone walked through it in the window before you did, and it does nothing for the next SSRF in a product you have not patched yet. The signal that spans all of them is egress that does not fit. An application server making a request to loopback, to a link-local address, to the metadata IP, or to an internal service it has never touched before is high-value and low-noise, because well-behaved apps almost never do it. That outbound anomaly is the detection point marked in the flow above, and it is the same tripwire whether the entry bug is this week's four or one nobody has disclosed. Patching closes the doors you know about. Watching your own egress is how you learn when someone used one you did not.

Methodology: figures are drawn from the Suriq threat desk's own intelligence and news ledgers over the stated window. "Triaged" counts events we logged a decision on, not raw signal volume; exploitation figures are best-effort and labelled approximate.

Topics

Frequently asked questions

What is SSRF and why is it worse in self-hosted software?

Server-side request forgery tricks an application into making an outbound request the attacker controls. It is worse in self-hosted software because the app runs inside your network, so its requests can reach cloud metadata, loopback admin ports, and internal services that no outsider could touch directly.

Which SSRF vulnerabilities were disclosed this week?

Four unrelated ones: CVE-2026-66794 in Red Hat Multicluster Engine for Kubernetes, CVE-2026-78003 in the Mailgun for WordPress plugin, CVE-2026-75899 in the fast-uri URL parser used by many Node.js apps, and CVE-2026-64849 in MLflow's webhook delivery.

Is any of this week's SSRF flaws being actively exploited?

Yes. MLflow's CVE-2026-64849 was added to CISA's Known Exploited Vulnerabilities catalog on August 19, 2026, with a federal patch deadline of September 2. The other three had no confirmed in-the-wild exploitation as of publication, but all are unauthenticated and should be treated as urgent.

How does SSRF let an attacker steal cloud credentials?

Many SSRF flaws can reach the cloud metadata service at 169.254.169.254, which returns the instance role's live credentials. MLflow's bug does this through DNS rebinding: it validates a hostname as public, then re-resolves it at delivery time to the metadata address and returns the response body.

How do you defend against SSRF beyond patching each CVE?

Control egress, not just ingress. Block app-server outbound access to 169.254.169.254, enforce IMDSv2 with a hop limit of 1, validate the resolved IP at connection time instead of the hostname, use short-lived credentials, and alert when an app server makes an unexpected outbound request.

Ready to meet the Guardians?

Deploys fast - agentless for monitoring and cloud, a lightweight agent for deep endpoint security. Just Suriq, standing watch.