When a patch for a critical vulnerability drops in a library downloaded over 500 million times a week, you expect it to be bulletproof. Developers quickly update their package.json, deploy to production, and sleep peacefully, assuming their internal services are safe again.
But what if the patch only fixed the symptom, leaving the root cause wide open?
Recently, my co-researcher Amol (@IAMolofficial) and I discovered a zero-day patch bypass in Axios (v1.15.0) that allowed a complete bypass of the newly implemented NO_PROXY protections. By leveraging a decades-old networking RFC, we found a way to expose over 16 million internal loopback addresses.
Here is the story of how our collaboration led to the discovery of CVE-2026–42043.
To understand the bypass, we first need to look at the original bug: CVE-2025–62718 (GHSA-3p68-rc4w-qgx5).
Axios, like many HTTP clients, respects the NO_PROXY environment variable. Developers commonly set NO_PROXY="localhost,127.0.0.1,::1" to ensure that requests to internal, local services don't accidentally get routed through an external corporate or attacker-controlled proxy.
However, prior to version 1.15.0, Axios performed a raw literal string match when checking NO_PROXY rules. An attacker could simply request http://localhost./ (with a trailing dot, indicating a Fully Qualified Domain Name) or http://[::1]/ (using IPv6 bracket notation). Because "localhost." !== "localhost", the check would fail, and Axios would happily route the sensitive local request through the proxy.
This resulted in a critical SSRF (Server-Side Request Forgery) vulnerability.
The Axios maintainers quickly released version 1.15.0 to fix this. They introduced a normalizeNoProxyHost() function to strip trailing dots and remove IPv6 brackets.
But they also added a cross-loopback equivalence check to ensure localhost and 127.0.0.1 were treated interchangeably. They did this by hardcoding a Set of recognized loopback addresses:
// lib/helpers/shouldBypassProxy.js — Axios 1.15.0
const LOOPBACK_ADDRESSES = new Set(['localhost', '127.0.0.1', '::1']);
const isLoopback = (host) => LOOPBACK_ADDRESSES.has(host);At first glance, this looks fine. It explicitly blocks the standard loopback representations. But during our research, we asked one fundamental question: Is this list actually complete?
Developers often assume that “loopback” strictly means 127.0.0.1. But operating systems don't think that way.
According to RFC 1122 §3.2.1.3, the standard that governs internet hosts:
“The address 127.0.0.0/8 is assigned for loopback. A datagram sent by a higher-level protocol to a loopback address MUST NOT appear on any network.”
Press enter or click to view image in full size
This means the loopback address isn’t just 127.0.0.1. It is the entire /8 subnet. Any IP address from 127.0.0.1 through 127.255.255.254 is a valid, functional loopback address that routes directly to your local machine.
Press enter or click to view image in full size
On Linux, the kernel automatically routes this entire subnet to the lo (loopback) interface by default.
Because the Axios patch used a strict Set.has() lookup against exactly three strings, it was completely blind to the rest of the subnet.
If a developer secured their app using NO_PROXY="localhost,127.0.0.1,::1", the patched Axios 1.15.0 would correctly block requests to 127.0.0.1.
But what if an attacker forced the application to make a request to http://127.0.0.2:8080/internal-api?
127.0.0.2LOOPBACK_ADDRESSES.has('127.0.0.2') -> FALSEResult: Silent interception of internal traffic.
Press enter or click to view image in full size
We wrote a quick Proof of Concept. While localhost. was successfully blocked (returning ECONNREFUSED), requests to 127.0.0.2, 127.0.0.100, and 127.1.2.3 were transparently forwarded to our attacker-controlled proxy server. The bypass was confirmed.
This wasn’t just a theoretical bypass; the real-world implications are severe.
Join Medium for free to get updates from this writer.
By exploiting this, an attacker can completely circumvent SSRF mitigations relying on NO_PROXY. If an internal microservice, admin dashboard, or Docker bridge network binds to a non-standard loopback IP, it is entirely exposed.
Furthermore, in cloud environments (AWS, GCP, Azure), internal metadata proxies or credential servers often bind to these alternate 127.x.x.x addresses. Routing this traffic through an attacker's proxy allows for silent data exfiltration and potential cloud account compromise. The worst part? It fails silently. The developer receives no error; the proxy interception is entirely transparent.
To remediate this, we didn’t just report the bug — we proposed a surgical fix. We needed to align the code with the RFC without impacting performance.
We proposed replacing the hardcoded Set with a logic-based check that validates the entire 127.0.0.0/8 subnet:
const isLoopback = (host) => {
if (host === 'localhost' || host === '::1') return true; // RFC 1122 §3.2.1.3: Matches any address from 127.0.0.0 through 127.255.255.254
const parts = host.split('.');
return (
parts.length === 4 &&
parts[0] === '127' &&
parts.every((p) => /^\d+$/.test(p) && Number(p) >= 0 && Number(p) <= 255)
);
};
But wait, what about IP obfuscation? Could an attacker bypass this new check using octal (0177.0.0.1) or integer (2130706433) IP formats?
Fortunately, no. Because Axios normalizes the request URL using Node.js’s native new URL() parser before passing it to this function, all alternative IP encodings are already resolved into their standard dotted-decimal IPv4 format. This 3-line fix is robust and RFC-compliant.
Finding a vulnerability is only half the battle; the other half relies entirely on the maintainers. We want to take a moment to express our deep appreciation for the Axios team.
Managing an open-source project with over half a billion weekly downloads is an incredibly high-pressure job. Yet, their response to our report was nothing short of exemplary. There was no ego, no friction, and no unnecessary delays. They triaged the issue immediately, accepted the report, and requested a CVE within hours.
This level of professionalism, speed, and dedication to security is exactly how open-source vulnerability disclosure should work. They set a gold standard for maintainers everywhere.
This vulnerability is a perfect reminder of a fundamental security principle: Code must reflect the reality of the underlying operating system. When developers build security controls based on assumptions (e.g., “localhost is always 127.0.0.1”) rather than networking standards (RFCs), gaps emerge.
We reported this finding via GitHub Security Advisories, and GitHub has officially assigned it CVE-2026–42043.
Official Advisories & Links
axios (npm)If you found this research interesting, feel free to connect with us on
https://www.linkedin.com/in/sachin-patil-sp/
https://github.com/sachinpatilpsp