Skip to content

Commit

Permalink
Limit maximum response size
Browse files Browse the repository at this point in the history
Fixes #1259
  • Loading branch information
kornelski committed Oct 17, 2017
1 parent 81f0512 commit 946e28d
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 0 deletions.
19 changes: 19 additions & 0 deletions lib/node/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -849,6 +849,24 @@ Request.prototype._end = function() {
}

var parserHandlesEnd = false;
if (buffer) {
// Protectiona against zip bombs and other nuisance
let responseBytesLeft = self._maxResponseSize || 200000000;
res.on('data', function(buf) {
responseBytesLeft -= buf.byteLength || buf.length;
if (responseBytesLeft < 0) {
// This will propagate through error event
const err = Error("Maximum response size reached");
err.code = "ETOOLARGE";
// Parsers aren't required to observe error event,
// so would incorrectly report success
parserHandlesEnd = false;
// Will emit error event
res.destroy(err);
}
});
}

if (parser) {
try {
// Unbuffered parsers are supposed to emit response early,
Expand Down Expand Up @@ -894,6 +912,7 @@ Request.prototype._end = function() {

// terminating events
res.once('error', function(err){
parserHandlesEnd = false;
self.callback(err, null);
});
if (!parserHandlesEnd) res.once('end', function(){
Expand Down
15 changes: 15 additions & 0 deletions lib/request-base.js
Original file line number Diff line number Diff line change
Expand Up @@ -413,6 +413,21 @@ RequestBase.prototype.redirects = function(n){
return this;
};

/**
* Maximum size of buffered response body, in bytes. Counts uncompressed size.
* Default 200MB.
*
* @param {Number} n
* @return {Request} for chaining
*/
RequestBase.prototype.maxResponseSize = function(n){
if ('number' !== typeof n) {
throw TypeError("Invalid argument");
}
this._maxResponseSize = n;
return this;
};

/**
* Convert to a plain javascript object (not JSON string) of scalar properties.
* Note as this method is designed to return a useful non-this value,
Expand Down
15 changes: 15 additions & 0 deletions test/node/inflate.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,21 @@ describe('zlib', function() {
});
});

it('should protect from zip bombs', function(done) {
request
.get(base)
.buffer(true)
.maxResponseSize(1)
.end(function(err, res) {
try {
assert.equal("Maximum response size reached", err && err.message);
done();
} catch(err) {
done(err);
}
});
});

it('should ignore trailing junk', function(done) {
request
.get(base + '/junk')
Expand Down

0 comments on commit 946e28d

Please sign in to comment.