Back to Blog
high SEVERITY8 min read

axios 1.18.1 CVE-2026-101898: HTTP/2 Ignores proxy and lookup

A dependency upgrade moved `axios` from 1.18.1 to 1.20.0 to pick up the fix for CVE-2026-101898, in which proxy and DNS resolution settings supplied through axios request configuration were not applied on the HTTP/2 request path. Applications that rely on `config.proxy`, `HTTP_PROXY`/`NO_PROXY` environment variables, or a custom `lookup` function as an SSRF or egress control could have those controls silently skipped for HTTP/2 requests.

O
By Orbis AppSec
•Technically reviewed by Anupam Mediratta•Published October 2, 2026•Reviewed October 2, 2026

Answer Summary

The vulnerability affects the `axios` HTTP client on npm; this dependency tree pinned 1.18.1, and the fix ships in 1.20.0. On the HTTP/2 request path, axios did not apply the proxy and DNS settings from the request configuration, so an attacker who controls or influences a request URL can cause traffic to skip a mandatory egress proxy and skip a custom `lookup` resolver used to block internal addresses — defeating SSRF allowlisting, DNS pinning, and outbound traffic logging. The fix is to upgrade to `axios` 1.20.0, which also raises the `form-data` constraint from `^4.0.5` to `^4.0.6`. No CWE identifier is recorded in the advisory data available for this finding; functionally it is a failure of an applied protection mechanism rather than a parsing bug.

Vulnerability at a Glance

cweN/A
fixUpgrade `axios` to 1.20.0, where the HTTP/2 path honours the same proxy and DNS settings as HTTP/1.1
riskSSRF allowlists, DNS-pinning `lookup` hooks, and mandatory egress proxies are silently skipped for HTTP/2 requests, allowing unmonitored outbound connections to attacker-chosen hosts and internal addresses
languageJavaScript / TypeScript (Node.js)
root causeThe HTTP/2 request path in axios 1.18.1 did not read `config.proxy`, proxy environment variables, or `config.lookup` when establishing the connection
vulnerabilitySecurity control bypass — proxy and DNS configuration not applied on the HTTP/2 transport path

Summary

axios 1.18.1 in this project's dependency tree carried CVE-2026-101898: on the HTTP/2 request path, the proxy and DNS settings supplied in axios request configuration were not applied. The lockfile now resolves axios at 1.20.0, which carries the upstream fix.

The important detail is what kind of bug this is. Nothing here crashes, corrupts memory, or injects a payload. Instead, a security control that developers deliberately configured — "all outbound traffic must go through this proxy", "resolve hostnames with this lookup function so internal IPs are rejected" — was quietly not honoured for a subset of requests. Controls that fail open are worse than controls that fail loudly, because the code looks correct, the tests pass, and the audit log is simply missing entries.

Introduction

Server-side HTTP clients are where SSRF defences live. A typical hardened Node.js service does something like this:

const http2 = require('http2');

await axios.get(userSuppliedUrl, {
  proxy: { host: 'egress.internal', port: 3128 },
  lookup: pinnedResolver,   // rejects 169.254.0.0/16, 10/8, ::1, etc.
  transport: http2,         // or an agent that negotiates h2 via ALPN
});

Two independent controls are in play. proxy forces every connection through an auditable, filtering egress hop. lookup replaces Node's DNS resolution so that a hostname resolving to a link-local or RFC 1918 address is refused before a socket is opened — the standard answer to DNS rebinding, where a name passes an allowlist check and then resolves to 169.254.169.254 a moment later.

CVE-2026-101898 is the discovery that, in affected axios 1.x releases, the HTTP/2 request path did not consult those settings. The proxy object, the HTTP_PROXY / HTTPS_PROXY / NO_PROXY environment variables resolved through proxy-from-env, and the custom lookup function were all ignored once a request went out over h2. The request still succeeded. It just went directly to the destination, resolved by the system resolver, with no proxy record of it ever happening.

For developers, the lesson generalises beyond axios: whenever a library grows a second transport, every security-relevant option has to be re-plumbed into it, and any option that is read on one path but not the other becomes a bypass.

Affected Versions

Affected unknown (this dependency tree resolved axios at 1.18.1)
Fixed in 1.20.0
Ecosystem npm
CVE / GHSA CVE-2026-101898 / GHSA not assigned
CWE unknown

Consult the upstream advisory for the authoritative affected range: CVE-2026-101898.

The Vulnerability Explained

This fix arrives as a lockfile change, so there is no application source to quote. The change is the resolved version of the axios dependency entry:

"node_modules/axios": {
-  "version": "1.18.1",
+  "version": "1.20.0",
   "dependencies": {
     "follow-redirects": "^1.16.0",
-    "form-data": "^4.0.5",
+    "form-data": "^4.0.6",
     "https-proxy-agent": "^5.0.1",
     "proxy-from-env": "^2.1.0"
   }

Those dependency names tell the story. proxy-from-env is how axios turns HTTP_PROXY / NO_PROXY into a proxy decision. https-proxy-agent is how it tunnels an HTTPS request through that proxy. Both are wired into the HTTP/1.1 adapter. The HTTP/2 path in 1.18.1 did not route through the same decision, so neither of those packages participated in the connection — and the user-supplied lookup function never reached the socket options either.

The problematic pattern

The defect is not a line of dangerous code; it is a missing read of configuration on a second code path:

  • HTTP/1.1 request → proxy resolution runs → lookup is passed to the connection → control enforced.
  • HTTP/2 request → connection established directly → proxy and lookup never consulted → control skipped.

Because both paths return a normal axios response, nothing in application code can tell the difference. response.status is 200 either way.

Attack scenario

Consider a webhook-validation endpoint that fetches a customer-supplied URL, with lookup pinned to reject private ranges and proxy pointing at the corporate egress gateway:

  1. An attacker submits https://attacker.example/callback, a host they control that advertises HTTP/2 via ALPN, or the service is configured to use the HTTP/2 transport for outbound calls.
  2. axios 1.18.1 takes the HTTP/2 path. The pinned lookup resolver is not installed on the connection, so resolution falls back to the system resolver.
  3. The attacker's authoritative DNS answers with a short-TTL record pointing at 169.254.169.254 (cloud metadata) or an internal service address. The DNS-pinning check that was supposed to block this never ran.
  4. The proxy is also skipped, so the gateway that would have blocked the destination — and, just as importantly, logged the attempt — sees nothing.

The realistic outcomes for a service running this code:

  • SSRF allowlisting defeated. A lookup-based guard is the main defence against rebinding; bypassing it reopens access to metadata endpoints, admin interfaces on loopback, and internal-only APIs.
  • Egress policy and DLP bypassed. In environments where the only sanctioned path off the host is the proxy, HTTP/2 requests leave unfiltered. Exfiltration over an axios call becomes invisible to proxy logs.
  • Broken detection, not just broken prevention. Incident responders reconstruct outbound activity from proxy records. Requests that never touched the proxy leave no trail.
  • NO_PROXY inversion. Deployments that rely on proxy environment variables for all traffic get an unintended direct-connect path, with no error and no warning.

Severity is rated high here because the bypass is silent, reachable from ordinary request configuration, and undermines a control specifically deployed against SSRF.

The Fix

The change is a single-dependency upgrade in the lockfile:

Before — axios resolved at 1.18.1, where the HTTP/2 path does not apply config.proxy, proxy environment variables, or config.lookup.

After — axios resolved at 1.20.0, which carries the upstream fix so that the HTTP/2 path honours the same proxy resolution and DNS lookup settings as the HTTP/1.1 adapter.

Two things moved in the lockfile entry, and it is worth separating them:

  1. version 1.18.1 → 1.20.0. This is the security-relevant change. It is what makes proxy, NO_PROXY, and lookup effective on HTTP/2 requests.
  2. form-data constraint ^4.0.5 → ^4.0.6. This is axios's own declared dependency metadata in 1.20.0, not an independent edit. It affects multipart encoding, not the HTTP/2 transport, and it comes along automatically with the upgrade.

No application code changes are required. The public configuration surface — proxy, lookup, transport, httpAgent, httpsAgent — is unchanged. That is precisely why this class of bug is dangerous and why the fix is cheap: call sites were already written correctly, and the library simply starts respecting them.

One caveat on verification. This fix was proposed from dependency metadata. The presence of axios 1.18.1 in the dependency tree is established; whether your code actually reaches the HTTP/2 request path was not verified. If you never enable an HTTP/2 transport and never use an agent that negotiates h2 over ALPN, your practical exposure is lower — but the upgrade is still the correct action, because transport selection can change with an agent swap or a dependency's defaults.

Verifying the upgrade landed:

npm ls axios        # expect 1.20.0, and check for nested duplicates

A nested axios under another package can remain on the vulnerable line even after the top-level entry is updated. If npm ls axios prints more than one version, resolve the transitive copy too.

Key Takeaways

  • config.proxy and config.lookup in axios 1.18.1 were applied on the HTTP/1.1 path but not the HTTP/2 path — if those options are your SSRF control, they were not enforced for h2 requests.
  • A security option that is accepted without error is not the same as one that is applied. Test enforcement, not acceptance: assert that a blocked internal address actually fails and that the proxy log contains the request.
  • DNS-pinning via a custom lookup function only protects connections where the resolver is actually installed on the socket. It is a client-side control with client-side failure modes.
  • Treat "the library gained a new transport" as a security event. Every proxy, DNS, TLS, and timeout option has to be re-plumbed into the new path, and any option read on only one path is a bypass.
  • Enforce egress at the network boundary — security groups, firewall rules, a transparent proxy — so that an in-process client bug cannot turn into unmonitored outbound traffic.

How Orbis AppSec Detected This

  • Source: the request URL and request configuration passed to the axios request API (axios.get(), axios.request(), instance methods), including proxy, lookup, and transport, where the target host may be influenced by untrusted input such as a user-supplied webhook or callback URL.
  • Sink: the outbound connection established on the axios HTTP/2 request path, which in 1.18.1 opened the socket without consulting the configured proxy resolution (proxy-from-env / https-proxy-agent) or the custom DNS lookup function.
  • Missing control: the HTTP/2 path did not read or apply the proxy and DNS settings from request configuration, so proxy enforcement and DNS-pinning allowlist checks were skipped for those requests with no error surfaced to the caller.
  • CWE: unknown — no CWE identifier is recorded in the advisory data available for this finding. Behaviourally, it is a configured protection mechanism that is not applied on a specific code path.
  • Fix: upgrade axios from 1.18.1 to 1.20.0, where the HTTP/2 path applies the same proxy and DNS lookup settings as the HTTP/1.1 adapter.

Orbis AppSec automatically detected this vulnerability and opened a pull request with the fix. Try Orbis AppSec on your repositories to find and fix issues like this automatically.

Conclusion

CVE-2026-101898 is a reminder that the most expensive vulnerabilities are not always the loudest ones. No crash, no injected payload, no stack trace — just a proxy object and a lookup function that axios 1.18.1 accepted and then ignored on HTTP/2 connections, turning a deliberate SSRF defence into decoration.

The remediation is a one-line lockfile change to axios 1.20.0, with the form-data constraint moving from ^4.0.5 to ^4.0.6 as a consequence of the upgrade. After upgrading, confirm with npm ls axios that no nested copy is still on the vulnerable line, and add a test that proves your egress proxy and DNS pinning actually reject a blocked destination rather than merely being configured.

Prevention and further reading

Frequently Asked Questions

Can I mitigate CVE-2026-101898 while staying on axios 1.18.1?

Partially — forcing requests onto HTTP/1.1 (not opting into the HTTP/2 transport, and not enabling ALPN upgrade in a custom agent) keeps traffic on the code path that does apply `config.proxy` and `config.lookup`. The durable mitigation is enforcing egress at the network layer rather than in the client, plus upgrading to 1.20.0.

Why did upgrading axios to 1.20.0 also change the `form-data` constraint from `^4.0.5` to `^4.0.6`?

`form-data` is a declared dependency of axios, and 1.20.0 raises its floor to `^4.0.6`. That is axios's own metadata change, not an edit made by the fix PR, and it only affects multipart body encoding — it is unrelated to the HTTP/2 proxy behaviour.

Does the fix require changing how `config.lookup` or `config.proxy` are passed to `axios.get()`?

No. The public configuration surface is unchanged; 1.20.0 simply makes the HTTP/2 path consume the same `proxy`, `NO_PROXY`, and `lookup` values that the HTTP/1.1 path already honoured, so existing call sites start behaving as they were already documented to behave.

View the Security Fix

Check out the pull request that fixed this vulnerability

View PR #1102

Related Articles

critical

Cloudflare Worker Reverse Proxy SSRF via String Concatenation

A Cloudflare Worker reverse proxy built its upstream request URL by string-concatenating an environment variable with the incoming request's pathname and search string, letting a crafted path or query redirect requests to attacker-chosen hosts. The fix replaces concatenation with the `URL` object's `pathname` and `search` setters, which normalize input against the configured origin instead of blindly appending it.

high

CVE-2026-42043: axios NO_PROXY Bypass via Malformed URL

CVE-2026-42043 is a high-severity vulnerability in axios where malformed URLs circumvent NO_PROXY environment variable protections, causing internal requests to route through attacker-controlled proxies. The fix upgrades axios from 1.13.6 to 1.18.0, introducing stricter proxy agent handling with `https-proxy-agent` and updated `follow-redirects`.

high

fast-uri 3.1.2 IDN Host Bypass: CVE-2026-13676 Upgrade

A dependency tree in this repository resolved `fast-uri` 3.1.2, a version affected by CVE-2026-13676, in which improper Unicode hostname canonicalization lets a crafted URI parse to one host while the HTTP client connects to another. Because `fast-uri` is what `ajv` uses to parse and resolve URIs for `format: "uri"` validation and `$ref` resolution, any host allowlist built on its parsed output could be bypassed. The fix upgrades the resolved copy to `fast-uri` 4.1.4 and pins it with an npm `ove

high

boardcards.js parseArgs() SSRF: --board Flag Reaches Metadata IPs

The `parseArgs()` function in boardcards.js accepted a user-controlled `--board` command-line argument and passed it directly to fetch() calls without validating the URL scheme or hostname. An attacker could supply `http://169.254.169.254/latest/meta-data/` or other internal addresses to extract cloud credentials or scan internal networks.

high

fetch() with Automatic Redirects Leaks HTTPS Trust to api.tomys.top

The `withProxy()` fetch wrapper allowed automatic HTTP redirects from `api.tomys.top`, trusting the external API's domain integrity without validating final destinations. A compromised or malicious redirect response could send users to attacker-controlled phishing sites while maintaining HTTPS protocol and hostname checks that falsely appear secure.

high

Voice Assistant Widget XSS: Unsanitized Bot Messages Execute in

The voice assistant widget's `appendMessage` function had a critical cross-site scripting (XSS) vulnerability where bot messages were inserted directly into the DOM without sanitization, while user messages were escaped. An attacker controlling bot responses could inject and execute arbitrary JavaScript in the user's browser context. The fix applies HTML escaping to all message types uniformly.