mirror of
https://github.com/tenrok/axios.git
synced 2026-06-17 19:21:29 +03:00
fix: guard socketPath with own() to prevent prototype pollution SSRF (#10901)
* fix: guard socketPath with own() to prevent prototype pollution SSRF
CVE-2026-42264 fix introduced the own() helper to guard config reads,
but socketPath and allowedSocketPaths were missed. An attacker who can
pollute Object.prototype.socketPath (via another dependency) can
redirect all axios requests to a Unix socket (e.g. Docker daemon),
enabling SSRF and container escape.
Fix: use own('socketPath') and own('allowedSocketPaths') instead of
direct config property access.
Ref: GHSA-72mg-mc2j-cwf6
Fixes: CVE-2026-42264 (complete)
* docs: add socketPath security release note
---------
Co-authored-by: Jay <jasonsaayman@gmail.com>
This commit is contained in:
@@ -9,6 +9,7 @@
|
||||
## Bug Fixes
|
||||
|
||||
- **AxiosHeaders:** Silently skip empty response header names emitted by some React Native Android responses instead of throwing. (**#6959**, **#10875**)
|
||||
- **HTTP Adapter - Socket Path:** Ignore inherited `socketPath` and `allowedSocketPaths` config values when building Node.js requests, preventing prototype-pollution SSRF via Unix sockets. (**#10901**)
|
||||
- **React Native FormData:** Clear the default `Content-Type` header for React Native `FormData` requests so Android can build multipart bodies with the correct boundary. (**#10898**)
|
||||
- **Request Data:** Preserve enumerable symbol keys when merging plain request data before `transformRequest`. (**#6392**)
|
||||
|
||||
|
||||
+11
-9
@@ -790,19 +790,21 @@ export default isHttpAdapterSupported &&
|
||||
// cacheable-lookup integration hotfix
|
||||
!utils.isUndefined(lookup) && (options.lookup = lookup);
|
||||
|
||||
if (config.socketPath) {
|
||||
if (typeof config.socketPath !== 'string') {
|
||||
const socketPath = own('socketPath');
|
||||
if (socketPath) {
|
||||
if (typeof socketPath !== 'string') {
|
||||
return reject(
|
||||
new AxiosError('socketPath must be a string', AxiosError.ERR_BAD_OPTION_VALUE, config)
|
||||
);
|
||||
}
|
||||
|
||||
if (config.allowedSocketPaths != null) {
|
||||
const allowed = Array.isArray(config.allowedSocketPaths)
|
||||
? config.allowedSocketPaths
|
||||
: [config.allowedSocketPaths];
|
||||
const allowedSocketPaths = own('allowedSocketPaths');
|
||||
if (allowedSocketPaths != null) {
|
||||
const allowed = Array.isArray(allowedSocketPaths)
|
||||
? allowedSocketPaths
|
||||
: [allowedSocketPaths];
|
||||
|
||||
const resolvedSocket = resolvePath(config.socketPath);
|
||||
const resolvedSocket = resolvePath(socketPath);
|
||||
const isAllowed = allowed.some(
|
||||
(entry) => typeof entry === 'string' && resolvePath(entry) === resolvedSocket
|
||||
);
|
||||
@@ -810,7 +812,7 @@ export default isHttpAdapterSupported &&
|
||||
if (!isAllowed) {
|
||||
return reject(
|
||||
new AxiosError(
|
||||
`socketPath "${config.socketPath}" is not permitted by allowedSocketPaths`,
|
||||
`socketPath "${socketPath}" is not permitted by allowedSocketPaths`,
|
||||
AxiosError.ERR_BAD_OPTION_VALUE,
|
||||
config
|
||||
)
|
||||
@@ -818,7 +820,7 @@ export default isHttpAdapterSupported &&
|
||||
}
|
||||
}
|
||||
|
||||
options.socketPath = config.socketPath;
|
||||
options.socketPath = socketPath;
|
||||
} else {
|
||||
options.hostname = parsed.hostname.startsWith('[')
|
||||
? parsed.hostname.slice(1, -1)
|
||||
|
||||
Reference in New Issue
Block a user