Skip to main content

SSRF defenses

The threat

Server-Side Request Forgery (SSRF) occurs when an attacker can influence the URL a server-side HTTP client requests. In axios, this was exploitable via CVE-2024-39338 and CVE-2025-27152, where absolute URLs or protocol-relative URLs (//evil.com/path) could override the configured baseURL.

How parcely prevents it

1. Reject absolute URLs when baseURL is set

When a baseURL is configured, parcely rejects any url that is absolute (starts with a protocol like http: or https:, or is protocol-relative like //host/path). This is controlled by:

const http = createClient({
baseURL: 'https://api.internal.com',
allowAbsoluteUrls: false, // this is the default when baseURL is set
})

// This throws HttpError with code: 'ERR_ABSOLUTE_URL'
await http.get('https://evil.com/steal-data')

// This also throws (protocol-relative URL)
await http.get('//evil.com/steal-data')

// This works (relative URL)
await http.get('/users/me')

2. Protocol allowlist

Even without a baseURL, parcely restricts which URI schemes are permitted:

const http = createClient({
allowedProtocols: ['http:', 'https:'], // default
})

// This throws HttpError with code: 'ERR_DISALLOWED_PROTOCOL'
await http.get('file:///etc/passwd')

Security table reference

These defenses correspond to rows 1 and 2 in the security defaults table:

#DefenseDefault
1Reject absolute URLs when baseURL is setallowAbsoluteUrls: false
2URI scheme allowlistallowedProtocols: ['http:', 'https:']

Opting out

If you genuinely need to send requests to arbitrary URLs:

const http = createClient({
baseURL: 'https://api.example.com',
allowAbsoluteUrls: true, // allow absolute URLs
})

This should be rare. If you find yourself opting out, consider whether the URL input is user-controlled and whether that creates an SSRF risk.