Safeguard
Vulnerability Analysis•

CVE-2026-16158: @fastify/reply-from Routes to the Wrong Upstream

@fastify/reply-from 8.3.1 up to 12.6.3 can reuse a cached URL for the wrong upstream (CVSS 8.7). Upgrade to 12.6.4 or set disableCache to true.

Safeguard Security Team
5 min read

CVE-2026-16158 affects @fastify/reply-from from 8.3.1 up to but not including 12.6.4, rated 8.7 (high). A cache key collision can send a request to a different upstream than the one intended. Upgrade to 12.6.4, or turn the URL cache off with the disableCache option until you can.

What's affected

  • Package: @fastify/reply-from on npm.
  • Affected: 8.3.1 up to but not including 12.6.4. The advisory text says 12.6.3 and earlier.
  • Fixed: 12.6.4.
  • Workaround from the advisory: set disableCache: true on the plugin registration. It prevents the collision but adds the cost of parsing the URL on every request.
  • Condition: applications that use the getUpstream() option to choose between security separated backends while the default URL cache is enabled, and where an attacker can influence the source path or the upstream selection.
  • Severity: 8.7, CWE-441. Not on the CISA Known Exploited Vulnerabilities list.

How to check if you're exposed

List every copy of the package, direct or transitive:

npm ls @fastify/reply-from

Any version from 8.3.1 up to 12.6.3 is in range. In a monorepo, run the command in each workspace. Container images deserve their own check, since the version inside the image is the one that serves traffic.

Next, look at how the plugin is registered. The advisory's condition is specific, so search for the option that selects an upstream per request:

grep -rn "getUpstream" --include=*.js --include=*.ts .

If nothing in your code or configuration chooses an upstream from request data, the described condition is not met, though the upgrade is still worthwhile. If it does, note which backends it can choose between and whether they sit at different trust levels, for example a public service and an internal one.

What to do now

  1. Upgrade @fastify/reply-from to 12.6.4 or later, and update the lockfile in each service that depends on it.
  2. If the upgrade has to wait, register the plugin with disableCache: true as the advisory suggests, and plan for the extra per request cost.
  3. Review each use of getUpstream(). Make sure the selection logic does not let a client steer toward a backend it should not reach.
  4. Make sure each backend still checks authorization on its own, so a misrouted request is refused at the destination.
  5. Redeploy and confirm the version running in production, then add the package to continuous dependency monitoring.

Why it matters

The advisory explains the mechanism in one sentence: the internal URL cache key is built by joining the destination and the source path with nothing between them. Two different pairs can therefore produce the same key. The advisory's own example uses a destination that ends in a port number and a source path that starts with a digit, where moving one character across the join gives the same text. Once one pair has filled the cache, the other pair reuses that cached URL and is forwarded to the wrong place without any error.

The weakness class is CWE-441, unintended proxy or intermediary, sometimes called a confused deputy. The proxy does exactly what it was told, but it was told the wrong thing by its own cache. The danger is highest where one proxy fronts services at different trust levels, because a request meant for the low trust backend can end up at the high trust one. The advisory states the impact as unauthorized cross upstream data access and modification, and it limits the scenario to cases where an attacker can influence the source path or the upstream selection.

This is a good example of a bug that a vulnerability score alone cannot rank. The base score is high, but whether you are exposed depends on a design choice: do you route between separated backends from request data, and do you leave the cache on. Reachability analysis helps here because it asks whether your code actually uses the affected function, not just whether the package is installed.

It is also a reminder about keys. Any cache keyed on two values needs a delimiter, or a structured key, that cannot be forged by shifting characters from one field to the other.

Try it yourself

Finding this package is the hard part, because it often arrives as a dependency of something else. This demo walks through building a dependency inventory.

Click through it at your own pace, or open it full screen.

Quick check

Is the cache on by default?

The advisory says the issue occurs with the default URL cache enabled, and it offers disableCache set to true as the workaround. That implies the cache is on unless you turn it off.

Do I need to worry if I use only one upstream?

The advisory describes the risk for setups that select between upstreams based on request data. With one fixed upstream the collision has nowhere different to send traffic, but upgrading is still the simplest fix.

Sources

Last reviewed: 19 October 2026.

Never miss an update

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

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.