mirror of
https://github.com/tenrok/axios.git
synced 2026-06-20 20:00:40 +03:00
fix: enforce max body length when max redirects is 0 (#10753)
This commit is contained in:
+35
-1
@@ -967,7 +967,41 @@ export default isHttpAdapterSupported &&
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
data.pipe(req);
|
// Enforce maxBodyLength for streamed uploads on the native http/https
|
||||||
|
// transport (maxRedirects === 0); follow-redirects enforces it on the
|
||||||
|
// other path. See GHSA-5c9x-8gcm-mpgx.
|
||||||
|
let uploadStream = data;
|
||||||
|
if (config.maxBodyLength > -1 && config.maxRedirects === 0) {
|
||||||
|
const limit = config.maxBodyLength;
|
||||||
|
let bytesSent = 0;
|
||||||
|
uploadStream = stream.pipeline(
|
||||||
|
[
|
||||||
|
data,
|
||||||
|
new stream.Transform({
|
||||||
|
transform(chunk, _enc, cb) {
|
||||||
|
bytesSent += chunk.length;
|
||||||
|
if (bytesSent > limit) {
|
||||||
|
return cb(
|
||||||
|
new AxiosError(
|
||||||
|
'Request body larger than maxBodyLength limit',
|
||||||
|
AxiosError.ERR_BAD_REQUEST,
|
||||||
|
config,
|
||||||
|
req
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
cb(null, chunk);
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
utils.noop
|
||||||
|
);
|
||||||
|
uploadStream.on('error', (err) => {
|
||||||
|
if (!req.destroyed) req.destroy(err);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
uploadStream.pipe(req);
|
||||||
} else {
|
} else {
|
||||||
data && req.write(data);
|
data && req.write(data);
|
||||||
req.end();
|
req.end();
|
||||||
|
|||||||
@@ -988,6 +988,82 @@ describe('supports http with nodejs', () => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should enforce maxBodyLength for streamed uploads with maxRedirects: 0 (GHSA-5c9x-8gcm-mpgx)', async () => {
|
||||||
|
let bytesReceived = 0;
|
||||||
|
const server = await startHTTPServer(
|
||||||
|
(req, res) => {
|
||||||
|
req.on('data', (chunk) => {
|
||||||
|
bytesReceived += chunk.length;
|
||||||
|
});
|
||||||
|
req.on('end', () => {
|
||||||
|
res.setHeader('Content-Type', 'application/json');
|
||||||
|
res.end(JSON.stringify({ received: bytesReceived }));
|
||||||
|
});
|
||||||
|
},
|
||||||
|
{ port: SERVER_PORT }
|
||||||
|
);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const size = 2 * 1024 * 1024;
|
||||||
|
const buf = Buffer.alloc(size, 0x61);
|
||||||
|
const source = stream.Readable.from([buf]);
|
||||||
|
|
||||||
|
await assert.rejects(
|
||||||
|
axios.post(`http://localhost:${server.address().port}/`, source, {
|
||||||
|
maxBodyLength: 1024,
|
||||||
|
maxRedirects: 0,
|
||||||
|
headers: { 'Content-Type': 'application/octet-stream' },
|
||||||
|
}),
|
||||||
|
(error) => {
|
||||||
|
assert.strictEqual(error.message, 'Request body larger than maxBodyLength limit');
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
assert.ok(
|
||||||
|
bytesReceived <= 1024 * 4,
|
||||||
|
`server should not receive full payload; got ${bytesReceived}`
|
||||||
|
);
|
||||||
|
} finally {
|
||||||
|
await stopHTTPServer(server);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should allow streamed uploads under maxBodyLength with maxRedirects: 0', async () => {
|
||||||
|
let bytesReceived = 0;
|
||||||
|
const server = await startHTTPServer(
|
||||||
|
(req, res) => {
|
||||||
|
req.on('data', (chunk) => {
|
||||||
|
bytesReceived += chunk.length;
|
||||||
|
});
|
||||||
|
req.on('end', () => {
|
||||||
|
res.setHeader('Content-Type', 'application/json');
|
||||||
|
res.end(JSON.stringify({ received: bytesReceived }));
|
||||||
|
});
|
||||||
|
},
|
||||||
|
{ port: SERVER_PORT }
|
||||||
|
);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const payload = Buffer.alloc(512, 0x62);
|
||||||
|
const source = stream.Readable.from([payload]);
|
||||||
|
|
||||||
|
const response = await axios.post(
|
||||||
|
`http://localhost:${server.address().port}/`,
|
||||||
|
source,
|
||||||
|
{
|
||||||
|
maxBodyLength: 1024,
|
||||||
|
maxRedirects: 0,
|
||||||
|
headers: { 'Content-Type': 'application/octet-stream' },
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
assert.strictEqual(response.data.received, payload.length);
|
||||||
|
} finally {
|
||||||
|
await stopHTTPServer(server);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
it('should properly support default max body length (follow-redirects as well)', async () => {
|
it('should properly support default max body length (follow-redirects as well)', async () => {
|
||||||
// Taken from follow-redirects defaults.
|
// Taken from follow-redirects defaults.
|
||||||
const followRedirectsMaxBodyDefaults = 10 * 1024 * 1024;
|
const followRedirectsMaxBodyDefaults = 10 * 1024 * 1024;
|
||||||
|
|||||||
Reference in New Issue
Block a user