← Back to Feed CACHED · 2026-05-17 09:42:19 · cache_key CVE-2025-29912
CVE-2026-44495 · CWE-94 · Disclosed 2026-05-29

axios Vulnerable to Credential Theft and Response Hijacking via Prototype Pollution Gadget in Config Merge

ASSESSED — NOISGATE V0.5
Vendor
Reassessed
Verdict:
01 · The Real Story

This is a burglar using an unlocked door inside the building, not kicking in the front gate

CVE-2026-44495 is an Axios *prototype-pollution gadget*, not a standalone entry point. In affected versions >=1.0.0,<1.15.2 and >=0.19.0,<0.31.1, Axios reads configuration through normal property access during mergeConfig(), so a pre-polluted Object.prototype.transformResponse can be treated as request config and later executed during response handling. In the full exploitation path, that function can read request URL, headers, and auth credentials and can alter the response seen by application code.

The vendor's HIGH 7.0 score is technically defensible in a vacuum but too generous for enterprise patch triage. The decisive friction is that Axios does not create the pollution itself; the attacker first needs a separate prototype-pollution bug or equivalent ability to control Object.prototype in the same runtime, and many real-world PP primitives only write JSON-like values rather than executable functions. That turns this from a broad unauthenticated remote event into a chained, context-dependent post-bug amplifier.

"Dangerous when chained, but this is not your initial-access fire drill; it needs prior prototype pollution in the same JS process."
02 · The Attack Path

4 steps from start to impact.

STEP 01

Land a helper bug that pollutes Object.prototype

The attacker first abuses a separate prototype-pollution primitive in the same Node.js process or browser context, using a vulnerable parser or merge utility such as qs, lodash, or similar gadget feeder named by the advisory. Without that upstream foothold, Axios is inert here. This is the single biggest severity reducer.
Conditions required:
  • A reachable prototype-pollution vulnerability elsewhere in the app or dependency tree
  • Attacker input reaches that vulnerable component before Axios builds a request
  • Axios runs in the same JS runtime as the polluted object graph
Where this breaks in practice:
  • Requires a second vulnerability or equivalent code execution/control path first
  • Many PP bugs only allow JSON-like values, not function objects
  • Modern SAST/SCA often flags common PP feeder libraries before this chain is viable
Detection/coverage: Network scanners will miss this. Code/SCA tools can flag both the helper PP CVE and vulnerable Axios versions; exploitability still needs manual chaining analysis.
STEP 02

Seed the Axios gadget with transformResponse

Using the polluted prototype, the attacker places a transformResponse value where Axios will inherit it during config merge. In fully affected versions, Axios can replace its default response transform with the polluted function and execute it with the request config bound as this. That exposes headers, URL, and any auth object passed to Axios.
Conditions required:
  • Affected Axios version
  • Polluted key is relevant to Axios config, especially transformResponse
  • Application does not override that key with a safe own property
Where this breaks in practice:
  • If the PP primitive cannot inject a function, full credential theft usually collapses into request failure/DoS
  • Some app patterns always set explicit transforms, narrowing reachable cases
  • Null-prototype wrappers or defensive cloning in app code can break inheritance
Detection/coverage: Runtime detection is weak unless you already monitor prototype mutations or suspicious outbound exfil from app processes. SCA catches version exposure, not live abuse.
STEP 03

Trigger an Axios request and harvest secrets

The attacker waits for the application to make a normal Axios call. When transformData() executes the polluted transform, it can read credentials from this.auth, inspect headers and response data, and return tampered content to the caller. The GHSA PoC shows both credential capture and response hijack behavior.
Conditions required:
  • The app actually uses Axios in the compromised process
  • Target requests carry useful secrets or trusted downstream data
  • The request path reaches response transformation
Where this breaks in practice:
  • Apps that avoid inline basic auth and keep secrets out of Axios config reduce impact
  • Short-lived tokens and service-mesh identity shrink credential value
  • Some requests may carry no sensitive headers or auth at all
Detection/coverage: EDR or eBPF app telemetry may spot unusual child behavior or outbound beacons, but there is no clean wire signature for 'Axios transform hijack.'
STEP 04

Abuse trust in the modified response

After theft, the attacker can also change the response body seen by business logic. That can suppress errors, falsify downstream API results, or poison application decisions inside the same process. The integrity impact is real, but narrower than full remote code execution or broad tenant escape.
Conditions required:
  • Application logic trusts Axios response content without secondary validation
  • Attacker-controlled transform returns a value compatible with call-site expectations
Where this breaks in practice:
  • Tampering is constrained by app behavior and type expectations
  • This does not directly yield OS-level RCE by itself
  • Blast radius stays inside the already-compromised app/runtime
Detection/coverage: Application logs may show anomalous success paths or malformed response objects, but most vulnerability scanners will not validate this semantic abuse.
03 · Intelligence Metadata

The supporting signals.

In-the-wild statusNo public evidence of active exploitation found in the reviewed sources, and not listed in CISA KEV at review time.
Proof-of-concept availabilityPublic PoC is embedded in the GitHub advisory and mirrored in OSV; weaponization effort is low once the helper prototype-pollution foothold already exists.
EPSSNo EPSS value was surfaced in the GitHub advisory at review time; treat exploit-probability telemetry as not yet mature / not surfaced for this newly published CVE.
KEV statusNo; no KEV entry found for CVE-2026-44495 as of 2026-06-03.
CVSS vector and what it meansCVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:L/A:L correctly captures the chain complexity better than the advisory's internal 9.4 thought experiment. The important bit is AC:H: exploitation depends on a separate upstream condition.
Affected versionsaxios >=1.0.0,<1.15.2 and >=0.19.0,<0.31.1 per GHSA.
Fixed versionsUpgrade to 1.15.2+ on the v1 line or 0.31.1+ on the v0 line. The release notes say the fix hardens resolveConfig/mergeConfig/validator paths to read only own properties and use null-prototype config objects.
Exposure / scanning realityThis is a library issue, not an internet-facing daemon, so Shodan/Censys/FOFA/GreyNoise are poor prioritization inputs here. Your real exposure comes from SBOMs, lockfiles, container layers, and node_modules across CI artifacts and app images.
Disclosure date2026-05-29 in the GitHub Advisory Database.
Reporter / sourcePublished by jasonsaayman to axios/axios; the advisory timeline says discovery occurred during a source code audit on 2026-04-15.
04 · The Call

noisgate verdict.

Final Verdict
DOWNGRADED to MEDIUM (5.8/10)

This lands in MEDIUM because the exploit chain starts with a prerequisite that already implies compromise: a separate prototype-pollution bug or equivalent attacker control over Object.prototype in the same JavaScript runtime. Axios is a powerful amplifier once that happens, but it is not a clean front-door remote exploit and its reachable population narrows further when the helper bug cannot inject function values.

HIGH Affected version ranges and fixed versions
HIGH Core exploit prerequisite: prior same-process prototype pollution
MEDIUM Real-world frequency of function-capable PP feeder chains in enterprise apps

Why this verdict

  • Downward pressure: requires a prior bug — the attacker needs a separate prototype-pollution foothold or equivalent runtime control before Axios is even in play.
  • Downward pressure: same-process requirement — this is not internet-reachable by itself; the helper bug and Axios must coexist in the same application runtime.
  • Downward pressure: many PP primitives are data-only — if the feeder bug can only set JSON-like values, impact often degrades to request breakage or DoS instead of credential theft.
  • Upward pressure: wide deployment — Axios is everywhere, so once the chain is viable the reachable population inside your software estate can be large.
  • Upward pressure: high-value data exposure — when exploited successfully, request URLs, headers, and auth credentials can be exposed across normal application traffic.

Why not higher?

Because this is fundamentally a chained issue. It assumes either another exploitable vulnerability or equivalent attacker control exists first, and that control must exist in the same JavaScript runtime before Axios merges config. That sharply narrows exploitability compared with true unauthenticated remote RCE/SSRF cases.

Why not lower?

Because once the chain is satisfied, the impact is not cosmetic. The advisory PoC shows access to request credentials and response data, and Axios is common enough that a single vulnerable package can sit inside many critical services. For exposed Node services with rich service-to-service credentials, the blast radius can be meaningful even if the entry condition is constrained.

05 · Compensating Control

What to do — in priority order.

  1. Kill upstream prototype-pollution feeders — Prioritize remediation of any reachable PP vulnerabilities in parsers, merge utilities, or request-processing libraries that run in the same process as Axios. This is the most effective compensating control because it removes the prerequisite the chain depends on; for a MEDIUM verdict there is no mitigation SLA, so use this as practical risk reduction while you work toward patching within the 365-day remediation window.
  2. Stop putting durable secrets in Axios config — Move away from static auth objects and long-lived API credentials in Axios request config where feasible; prefer short-lived tokens from workload identity or service mesh auth. That does not fix the bug, but it strips value from the data the polluted transform can read; for MEDIUM, there is no mitigation SLA and this is best treated as architecture hardening while patching proceeds.
  3. Inventory lockfiles and images — Use SBOMs, package-lock.json, pnpm-lock.yaml, yarn.lock, and container image scans to find transitive Axios usage across services rather than relying on asset scanners. This matters because library exposure is invisible on the network; for MEDIUM, there is no mitigation SLA — go straight to remediation planning within 365 days.
  4. Harden runtime against prototype abuse — Where app compatibility allows, freeze sensitive prototypes, use null-prototype objects for config-like structures, and add tests that fail on inherited config keys. This is defensive engineering rather than a substitute for the vendor fix, and under a MEDIUM verdict it should be scheduled as part of the normal remediation window.
What doesn't work
  • A WAF does not solve this by itself; the exploit depends on an in-process JavaScript object state, not just a recognisable HTTP signature.
  • Network vuln scanning does not meaningfully detect this; Axios is a package inside apps and containers, not a listening service with a banner.
  • MFA is irrelevant here; there is no login boundary in the Axios gadget path.
  • Blocking only outbound traffic is incomplete; it may stop exfiltration to the internet, but it does not stop response tampering or theft of internal service credentials used in-process.
06 · Verification

Crowdsourced verification payload.

Run this on a build worker, source checkout, or application host that has the project files available. Invoke it with python3 check_axios_cve_2026_44495.py /path/to/app and no elevated privileges are required; it inspects package-lock.json, npm-shrinkwrap.json, and node_modules/axios/package.json and prints VULNERABLE, PATCHED, or UNKNOWN.

noisgate-verify.py
PYTHONREAD-ONLYSAFE
#!/usr/bin/env python3
# check_axios_cve_2026_44495.py
# Detect vulnerable axios versions for CVE-2026-44495.
# Exit codes: 0=PATCHED, 1=VULNERABLE, 2=UNKNOWN, 3=usage/error

import json
import os
import sys
from typing import List, Optional, Tuple

AFFECTED_RANGES = [
    ((1, 0, 0), (1, 15, 2)),   # >=1.0.0, <1.15.2
    ((0, 19, 0), (0, 31, 1)),  # >=0.19.0, <0.31.1
]


def parse_ver(v: str) -> Optional[Tuple[int, int, int]]:
    if not v:
        return None
    v = v.strip()
    if v.startswith('v'):
        v = v[1:]
    core = v.split('-')[0].split('+')[0]
    parts = core.split('.')
    nums = []
    for p in parts:
        digits = ''
        for ch in p:
            if ch.isdigit():
                digits += ch
            else:
                break
        if digits == '':
            nums.append(0)
        else:
            nums.append(int(digits))
    while len(nums) < 3:
        nums.append(0)
    return tuple(nums[:3])


def is_affected(v: str) -> Optional[bool]:
    pv = parse_ver(v)
    if pv is None:
        return None
    for low, high in AFFECTED_RANGES:
        if pv >= low and pv < high:
            return True
    return False


def walk_deps(dep_obj, found: List[Tuple[str, str, str]], source: str, path: str = ''):
    if not isinstance(dep_obj, dict):
        return
    for name, meta in dep_obj.items():
        if not isinstance(meta, dict):
            continue
        ver = meta.get('version')
        current_path = f"{path}>{name}" if path else name
        if name == 'axios' and isinstance(ver, str):
            found.append((source, current_path, ver))
        nested = meta.get('dependencies')
        if isinstance(nested, dict):
            walk_deps(nested, found, source, current_path)


def inspect_package_lock(lock_path: str, found: List[Tuple[str, str, str]]):
    try:
        with open(lock_path, 'r', encoding='utf-8') as f:
            data = json.load(f)
    except Exception:
        return

    # npm lockfile v2/v3
    packages = data.get('packages')
    if isinstance(packages, dict):
        for pkg_path, meta in packages.items():
            if not isinstance(meta, dict):
                continue
            if pkg_path.endswith('node_modules/axios'):
                ver = meta.get('version')
                if isinstance(ver, str):
                    found.append((lock_path, pkg_path, ver))

    # npm lockfile v1 style
    deps = data.get('dependencies')
    if isinstance(deps, dict):
        walk_deps(deps, found, lock_path)


def inspect_node_modules(base: str, found: List[Tuple[str, str, str]]):
    pkg_json = os.path.join(base, 'node_modules', 'axios', 'package.json')
    if not os.path.isfile(pkg_json):
        return
    try:
        with open(pkg_json, 'r', encoding='utf-8') as f:
            data = json.load(f)
        ver = data.get('version')
        if isinstance(ver, str):
            found.append((pkg_json, 'node_modules/axios', ver))
    except Exception:
        return


def main():
    if len(sys.argv) != 2:
        print('UNKNOWN - usage: python3 check_axios_cve_2026_44495.py /path/to/app')
        sys.exit(3)

    target = os.path.abspath(sys.argv[1])
    if not os.path.exists(target):
        print(f'UNKNOWN - path does not exist: {target}')
        sys.exit(3)

    found: List[Tuple[str, str, str]] = []

    if os.path.isfile(target):
        name = os.path.basename(target)
        if name in ('package-lock.json', 'npm-shrinkwrap.json'):
            inspect_package_lock(target, found)
        else:
            print('UNKNOWN - provide an app directory or package-lock.json/npm-shrinkwrap.json')
            sys.exit(2)
    else:
        for root, dirs, files in os.walk(target):
            # keep traversal bounded-ish
            if '.git' in dirs:
                dirs.remove('.git')
            if name := next((x for x in ('package-lock.json', 'npm-shrinkwrap.json') if x in files), None):
                inspect_package_lock(os.path.join(root, name), found)
            inspect_node_modules(root, found)

    # de-duplicate
    uniq = []
    seen = set()
    for item in found:
        if item not in seen:
            uniq.append(item)
            seen.add(item)

    if not uniq:
        print('UNKNOWN - no axios installation or supported npm lockfile evidence found')
        sys.exit(2)

    vulnerable = []
    patched = []
    unknown = []

    for source, dep_path, ver in uniq:
        affected = is_affected(ver)
        rec = f'{ver} [{dep_path}] ({source})'
        if affected is True:
            vulnerable.append(rec)
        elif affected is False:
            patched.append(rec)
        else:
            unknown.append(rec)

    if vulnerable:
        print('VULNERABLE - CVE-2026-44495 affected axios versions detected:')
        for r in vulnerable:
            print(f'  - {r}')
        if patched:
            print('Also found patched versions:')
            for r in patched:
                print(f'  - {r}')
        sys.exit(1)

    if patched and not unknown:
        print('PATCHED - only fixed axios versions detected:')
        for r in patched:
            print(f'  - {r}')
        sys.exit(0)

    print('UNKNOWN - no vulnerable versions detected, but some evidence was inconclusive:')
    for r in patched:
        print(f'  - patched: {r}')
    for r in unknown:
        print(f'  - unknown: {r}')
    sys.exit(2)


if __name__ == '__main__':
    main()
07 · Bottom Line

If you remember one thing.

TL;DR
Monday morning, treat this as a dependency-chain cleanup item, not an emergency all-hands remote-code-exec event. First, identify where Axios is actually present in production apps, images, and CI lockfiles, then cross-check whether those apps also carry reachable prototype-pollution feeder bugs or store durable credentials in Axios config. Because this verdict is MEDIUM, there is no noisgate mitigation SLA — go straight to the 365-day remediation window; there is likewise no separate mitigation deadline, and the noisgate remediation SLA is to get the vendor-fixed versions (1.15.2+ or 0.31.1+) deployed within 365 days through normal dependency update waves, with earlier pull-forward for internet-facing Node services or apps already carrying PP-prone parser libraries.

Sources

  1. GitHub Advisory GHSA-3g43-6gmg-66jw
  2. OSV entry for GHSA-3g43-6gmg-66jw
  3. Axios release v1.15.2
  4. Axios release v0.31.1
  5. Axios repository
  6. npm package page for axios
  7. CISA Known Exploited Vulnerabilities Catalog
  8. FIRST EPSS documentation
Peer Review

What defenders are saying.

Submit a review attribution: handle + country only
0 flags selected · stored anonymously
Validation Results

Crowdsourced verification outputs.

Results submitted by users who ran the verification payload against their environment.