Back to Blog
critical SEVERITY7 min read

How SSRF via Vulnerable Dependency Versions Happens in Node.js and How to Fix It

A permissive semver range in `package.json` allowed npm to install axios versions vulnerable to SSRF (CVE-2024-39338). By bumping the minimum version from `^1.6.0` to `^1.7.4`, all downstream consumers of this SDK are now protected from server-side request forgery attacks. This critical fix required changing just one line in the dependency manifest.

O
By Orbis AppSec
Published September 3, 2026Reviewed September 3, 2026

Answer Summary

CVE-2024-39338 is a Server-Side Request Forgery (SSRF) vulnerability in axios versions prior to 1.7.4, classified as CWE-918. In a Node.js `package.json`, specifying `"axios": "^1.6.0"` allows npm to resolve any version from 1.6.0 to <2.0.0, including vulnerable releases. The fix is to update the semver range to `"axios": "^1.7.4"`, ensuring only patched versions are installed.

Vulnerability at a Glance

cweCWE-918
fixUpdated minimum axios version from `^1.6.0` to `^1.7.4` in `package.json`
riskAttackers can exploit SSRF to access internal services, cloud metadata endpoints, or bypass firewalls
languageJavaScript / Node.js
root causePermissive caret semver range `^1.6.0` allowed installation of axios versions with known SSRF vulnerability (CVE-2024-39338)
vulnerabilityServer-Side Request Forgery (SSRF) via vulnerable dependency

Introduction

In a Node.js SDK's package.json at line 22, we discovered a critical dependency version issue that left every downstream consumer of the library exposed to Server-Side Request Forgery (SSRF). The culprit? A single caret character and a version number:

"axios": "^1.6.0"

This seemingly innocuous semver range told npm: "install any axios version from 1.6.0 up to, but not including, 2.0.0." The problem is that axios versions before 1.7.4 contain CVE-2024-39338, a well-documented SSRF vulnerability. Because this file belongs to a published library—not just an internal application—every project that depends on this SDK inherits the risk. A fresh npm install could silently resolve to axios 1.6.8 or 1.7.2, both of which are exploitable.

This matters for any developer who maintains Node.js packages or consumes third-party SDKs: your package.json version ranges are part of your attack surface.

The Vulnerability Explained

What is CVE-2024-39338?

CVE-2024-39338 is a Server-Side Request Forgery vulnerability in axios, one of the most widely-used HTTP client libraries in the JavaScript ecosystem (over 50 million weekly npm downloads). In vulnerable versions, an attacker can manipulate request URLs to cause the server to make unintended HTTP requests to internal resources.

How the Semver Range Creates the Problem

npm's caret (^) operator follows semantic versioning rules. When package.json specifies:

"dependencies": {
    "axios": "^1.6.0"
}

npm will resolve to the latest compatible version at install time. But here's the critical nuance: if a consumer's lockfile is stale, regenerated, or absent, npm could resolve to any version in the range >=1.6.0 <2.0.0. Versions 1.6.0 through 1.7.3 all contain the SSRF vulnerability.

A Concrete Attack Scenario

Imagine a backend service that uses this SDK to interact with an external API. The SDK internally uses axios to make HTTP requests. Here's how an attacker could exploit this:

  1. Reconnaissance: The attacker identifies that a target application uses this SDK (via exposed package-lock.json, error messages, or HTTP headers).
  2. Version check: They determine the installed axios version is 1.7.2 (within the ^1.6.0 range but below the patched 1.7.4).
  3. SSRF exploitation: The attacker crafts input that causes the SDK's axios instance to make a request to an internal endpoint—for example, http://169.254.169.254/latest/meta-data/ on AWS to retrieve instance metadata and IAM credentials.
  4. Escalation: With stolen cloud credentials, the attacker pivots to access S3 buckets, databases, or other cloud resources.

Because this is a library (note the microbundle dev dependency for bundling), the blast radius extends to every application that depends on it. The library authors may not even be aware that their consumers are running vulnerable axios versions.

Why This Is Critical

  • Supply chain amplification: A single vulnerable dependency in a published library propagates to all consumers.
  • Silent vulnerability: Developers installing the SDK have no indication they're getting a vulnerable axios version.
  • Cloud metadata exposure: SSRF is particularly dangerous in cloud environments where metadata endpoints are accessible from the server.

The Fix

The fix is surgical: update the minimum acceptable axios version from 1.6.0 to 1.7.4 in package.json at line 23.

Before (Vulnerable)

"dependencies": {
    "axios": "^1.6.0"
}

This allows npm to install any axios version from 1.6.0 to <2.0.0, including versions vulnerable to CVE-2024-39338.

After (Fixed)

"dependencies": {
    "axios": "^1.7.4"
}

This ensures npm will only resolve to axios 1.7.4 or later (up to <2.0.0), all of which contain the SSRF patch.

Why This Specific Change Works

  1. Floor elevation: By raising the minimum from 1.6.0 to 1.7.4, every version in the new range (>=1.7.4 <2.0.0) has the CVE-2024-39338 fix applied.
  2. Backward compatibility preserved: The caret operator still allows minor and patch updates, so consumers benefit from future bug fixes without manual intervention.
  3. No source code changes required: Because this is a dependency version constraint—not a code change—there is zero risk of behavioral regression. The SDK's source files remain untouched.
  4. Downstream propagation: When library consumers run npm update or regenerate their lockfiles, they'll automatically get a safe axios version.

Important Caveat

Existing consumers with a package-lock.json that already resolved to an older axios version will need to run npm update axios or delete their lockfile and reinstall. The fix in package.json ensures that new installations and lockfile regenerations will always get a patched version.

Prevention & Best Practices

1. Set Version Floors Above Known CVEs

When specifying dependency ranges, don't just use the version you originally developed against. Regularly review whether your minimum version floor excludes known-vulnerable releases:

// ❌ Allows vulnerable versions
"axios": "^1.6.0"

// ✅ Floor set above the CVE-2024-39338 fix
"axios": "^1.7.4"

2. Run npm audit in CI/CD

Add npm audit --audit-level=high to your CI pipeline. This catches known CVEs in your dependency tree before they reach production:

# GitHub Actions example
- name: Security audit
  run: npm audit --audit-level=high

3. Use Lockfiles and Review Them

Always commit package-lock.json (or yarn.lock). Lockfiles pin exact resolved versions, preventing surprise installations of vulnerable releases. Review lockfile changes in PRs to catch unexpected version changes.

4. Automate Dependency Updates

Use tools like Dependabot, Renovate, or Orbis AppSec to automatically detect and fix vulnerable dependency versions. Manual tracking of CVEs across hundreds of transitive dependencies is unsustainable.

5. Apply Defense in Depth for SSRF

Even with patched dependencies, implement application-level SSRF protections:
- URL allowlisting: Only permit requests to known-good domains.
- Block internal IP ranges: Reject requests to 127.0.0.0/8, 169.254.0.0/16, 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16.
- Disable HTTP redirects or validate redirect targets.
- Network segmentation: Use VPCs and security groups to limit what your application servers can reach.

6. Reference Standards

  • CWE-918: Server-Side Request Forgery — understand the full taxonomy of SSRF patterns.
  • OWASP SSRF Prevention Cheat Sheet: Comprehensive guidance on mitigating SSRF at every layer.

Key Takeaways

  • A permissive semver range like ^1.6.0 is an implicit trust statement that every version from 1.6.0 to <2.0.0 is safe—verify this assumption regularly against CVE databases.
  • Library maintainers bear responsibility for their consumers' security: this SDK's package.json directly controlled which axios versions downstream applications could install.
  • CVE-2024-39338 in axios <1.7.4 enables SSRF, which is especially dangerous in cloud environments where instance metadata endpoints (169.254.169.254) can leak IAM credentials.
  • The fix was a one-character, two-digit change (^1.6.0^1.7.4)—proof that critical security improvements don't always require complex code refactoring.
  • npm audit alone isn't enough for libraries: audit checks your resolved lockfile, but library consumers resolve versions independently. The version range in package.json is the only control library authors have.

How Orbis AppSec Detected This

  • Source: The package.json dependency declaration at line 23, where the axios version range ^1.6.0 allows resolution to versions containing CVE-2024-39338.
  • Sink: Any axios HTTP request call within the SDK or its consumers, where SSRF payloads could be processed by a vulnerable axios version (versions <1.7.4).
  • Missing control: No minimum version floor was set above the patched axios release (1.7.4). The semver range permitted installation of 18 months' worth of vulnerable axios releases.
  • CWE: CWE-918 — Server-Side Request Forgery (SSRF)
  • Fix: Updated the axios dependency range from ^1.6.0 to ^1.7.4 in package.json, ensuring only versions with the CVE-2024-39338 patch can be installed.

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

This vulnerability is a textbook example of how supply chain security failures cascade. A single permissive version range in a library's package.json silently exposed every downstream consumer to a well-known SSRF vulnerability (CVE-2024-39338). The fix—bumping "axios": "^1.6.0" to "axios": "^1.7.4"—is minimal in size but critical in impact.

For library maintainers: treat your package.json version ranges as security boundaries, not just compatibility hints. For application developers: audit your transitive dependencies, not just your direct ones. And for everyone: automate dependency scanning so that known CVEs never silently enter your production builds.

References

Frequently Asked Questions

What is SSRF (Server-Side Request Forgery)?

SSRF is a vulnerability where an attacker can induce the server-side application to make HTTP requests to an arbitrary domain of the attacker's choosing, potentially accessing internal services, cloud metadata endpoints, or other restricted resources.

How do you prevent SSRF via dependencies in Node.js?

Pin dependencies to known-safe versions, regularly audit with `npm audit`, use lockfiles, and set minimum version floors that exclude versions with known CVEs. Automated dependency scanning tools can catch outdated or vulnerable packages.

What CWE is SSRF?

SSRF is classified as CWE-918: Server-Side Request Forgery. It describes flaws where a web application fetches a remote resource based on a user-supplied URL without sufficient validation.

Is pinning exact versions enough to prevent SSRF in dependencies?

Pinning exact versions prevents installing known-vulnerable releases, but it's not sufficient alone. You also need regular auditing, automated alerts for new CVEs, and defense-in-depth measures like network segmentation and URL allowlists in your application code.

Can static analysis detect SSRF vulnerabilities in dependencies?

Yes. Tools like `npm audit`, Snyk, Dependabot, and multi-agent AI scanners can detect known vulnerable dependency versions. Software Composition Analysis (SCA) tools specifically track CVEs against your dependency tree and alert on exploitable versions.

View the Security Fix

Check out the pull request that fixed this vulnerability

View PR #84

Related Articles

critical

How Server-Side Request Forgery (SSRF) happens in JavaScript and how to fix it

A critical Server-Side Request Forgery (SSRF) vulnerability was discovered in playground.html where the `__forEachRdfMessageChunkFromUrl` function fetched user-controlled URLs without validating against private IP ranges or internal network addresses. The fix introduces a comprehensive `__isBlockedFetchUrl` validation function that blocks requests to localhost, private IP ranges, and link-local addresses before any fetch occurs.

critical

How Server-Side Request Forgery happens in Python FastAPI and how to fix it

A critical Server-Side Request Forgery (SSRF) vulnerability was discovered in app.py where the `/parse` and `/parse-video` endpoints accepted user-supplied URLs with only substring validation. The application checked if 'doubao.com' appeared anywhere in the URL string, allowing attackers to bypass this check and access internal services, cloud metadata endpoints, or scan the internal network. The fix implemented proper hostname parsing with an allowlist of legitimate domains.

critical

How Server-Side Request Forgery happens in Node.js maintenance scripts and how to fix it

A critical Server-Side Request Forgery (SSRF) vulnerability was discovered in `maintenance/getImages.js`, where the `getImage()` function passed database-sourced URLs directly to `axios.get()` without any validation. An attacker who could modify the elements database could redirect these requests to internal network resources — including AWS cloud metadata endpoints — potentially exposing IAM credentials and other sensitive infrastructure data. The fix introduces a strict URL allowlist that limi

high

How SSRF via inconsistent IP address parsing happens in Node.js dependencies and how to fix it

A high-severity flaw (CVE-2026-69192) in the widely-used `ip-address` npm package meant that IP strings could be parsed inconsistently compared to the OS resolver and Node's own networking stack — letting an attacker slip a private/loopback address past an allowlist that used `Address4`/`Address6` for validation. This PR pins and upgrades `ip-address` from `10.1.0` to `10.3.1` in both `package.json` (via `overrides`) and `package-lock.json`, eliminating the parser divergence across the whole dep

high

How Octal IP Address Parsing Leads to SSRF in Node.js and How to Fix It

CVE-2026-69192 reveals a critical inconsistency in the `ip-address` library where Address4 decodes leading-zero octets as decimal while DNS resolvers interpret them as octal, creating a dangerous parsing divergence. This mismatch allows attackers to bypass IP-based access controls and perform Server-Side Request Forgery (SSRF) attacks. The fix upgrades `ip-address` from 9.0.5 to 10.3.1, aligning parsing behavior with standard resolver implementations.

critical

How Path Traversal happens in Node.js Express servers and how to fix it

A path traversal vulnerability in `src/server.js` allowed attackers to escape the intended wiki directory by sending encoded traversal sequences through the `/api/pages/:slug(*)` wildcard endpoint. The flawed `startsWith` boundary check could be bypassed after `decodeURIComponent` processing, potentially exposing arbitrary files on the server. The fix replaces the inline filesystem logic with a dedicated `readWikiPage()` function that enforces proper path validation.