# Axios: HTTP/2 adapter bypasses configured DNS lookup and proxy controls

Axios HTTP/2 adapter drops config.lookup and proxy settings, letting user-influenced URLs reach internal or loopback destinations that SSRF policy should block.

- Payout: Research
- Severity: high
- Program: Axios
- Found by: HamdaanAliQuatil
- Disclosed: 2026-09-30
- CVE: CVE-2026-101898
- Write-up quality: 7/10
- Original: https://github.com/advisories/GHSA-3pq3-5fj3-cg6v
- Library page: https://bugbountylibrary.com/r/ghsa%3AGHSA-3pq3-5fj3-cg6v
- Tags: area:oss domain:oss impact:internal-access kind:research platform:ghsa sev:high tech:nodejs technique:chained technique:source-review vuln:ssrf

**Target:** Node.js HTTP client library (npm axios) HTTP/2 transport
**Root cause:** The HTTP/2 transport builds a session via `http2.connect(authority, http2Options)` passing only `options.http2Options`, so the top-level `lookup`, proxy tunneling agent from `setProxy()`, and selected agents are never forwarded; the session uses the system resolver and a direct connection.
**Steps:**
1. Start an HTTPS origin with HTTP/2 enabled that records requests and returns `REACHED_BLOCKED_ORIGIN`.
2. Start an HTTP proxy that rejects every request and CONNECT with `502 Bad Gateway` and logs traffic.
3. Define a custom axios `lookup` that rejects every DNS lookup with `EPOLICY`.
4. Control: `axios.get(url, { lookup })` over HTTP/1 fails with `EPOLICY` and never reaches origin.
5. Attack: `axios.get(url, { httpVersion: 2, http2Options: { rejectUnauthorized: false }, proxy, lookup })` returns 200 `REACHED_BLOCKED_ORIGIN`; lookup counter unchanged, proxy sees no traffic.
**How found:** Compared the HTTP/1 adapter path (which wraps `lookup`, builds options, calls `setProxy()`) against the HTTP/2 transport, noticing `http2.connect()` receives only `http2Options` and drops top-level lookup/agent/proxy state; verified with a local three-listener PoC on axios 1.18.1.
**Exploitation:** An app that lets users supply URLs and relies on axios `lookup` or mandatory proxy for egress policy is bypassed by setting `httpVersion: 2`; axios connects directly via system resolver to loopback, private, or link-local services, enabling metadata credential theft or state-changing internal requests.
**Insight:** When a library has parallel transport implementations (HTTP/1 vs HTTP/2, sync vs async clients), diff which security-relevant config keys each path forwards into the low-level connect call; policy hooks like custom resolvers and proxy agents are commonly dropped in the newer/experimental path.

