mirror of
https://github.com/tenrok/axios.git
synced 2026-06-23 20:40:40 +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
|
## Bug Fixes
|
||||||
|
|
||||||
- **AxiosHeaders:** Silently skip empty response header names emitted by some React Native Android responses instead of throwing. (**#6959**, **#10875**)
|
- **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**)
|
- **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**)
|
- **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
|
// cacheable-lookup integration hotfix
|
||||||
!utils.isUndefined(lookup) && (options.lookup = lookup);
|
!utils.isUndefined(lookup) && (options.lookup = lookup);
|
||||||
|
|
||||||
if (config.socketPath) {
|
const socketPath = own('socketPath');
|
||||||
if (typeof config.socketPath !== 'string') {
|
if (socketPath) {
|
||||||
|
if (typeof socketPath !== 'string') {
|
||||||
return reject(
|
return reject(
|
||||||
new AxiosError('socketPath must be a string', AxiosError.ERR_BAD_OPTION_VALUE, config)
|
new AxiosError('socketPath must be a string', AxiosError.ERR_BAD_OPTION_VALUE, config)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config.allowedSocketPaths != null) {
|
const allowedSocketPaths = own('allowedSocketPaths');
|
||||||
const allowed = Array.isArray(config.allowedSocketPaths)
|
if (allowedSocketPaths != null) {
|
||||||
? config.allowedSocketPaths
|
const allowed = Array.isArray(allowedSocketPaths)
|
||||||
: [config.allowedSocketPaths];
|
? allowedSocketPaths
|
||||||
|
: [allowedSocketPaths];
|
||||||
|
|
||||||
const resolvedSocket = resolvePath(config.socketPath);
|
const resolvedSocket = resolvePath(socketPath);
|
||||||
const isAllowed = allowed.some(
|
const isAllowed = allowed.some(
|
||||||
(entry) => typeof entry === 'string' && resolvePath(entry) === resolvedSocket
|
(entry) => typeof entry === 'string' && resolvePath(entry) === resolvedSocket
|
||||||
);
|
);
|
||||||
@@ -810,7 +812,7 @@ export default isHttpAdapterSupported &&
|
|||||||
if (!isAllowed) {
|
if (!isAllowed) {
|
||||||
return reject(
|
return reject(
|
||||||
new AxiosError(
|
new AxiosError(
|
||||||
`socketPath "${config.socketPath}" is not permitted by allowedSocketPaths`,
|
`socketPath "${socketPath}" is not permitted by allowedSocketPaths`,
|
||||||
AxiosError.ERR_BAD_OPTION_VALUE,
|
AxiosError.ERR_BAD_OPTION_VALUE,
|
||||||
config
|
config
|
||||||
)
|
)
|
||||||
@@ -818,7 +820,7 @@ export default isHttpAdapterSupported &&
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
options.socketPath = config.socketPath;
|
options.socketPath = socketPath;
|
||||||
} else {
|
} else {
|
||||||
options.hostname = parsed.hostname.startsWith('[')
|
options.hostname = parsed.hostname.startsWith('[')
|
||||||
? parsed.hostname.slice(1, -1)
|
? parsed.hostname.slice(1, -1)
|
||||||
|
|||||||
Reference in New Issue
Block a user