Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,9 @@ jobs:
- name: Node.js 25.x
node-version: "25"

- name: Node.js 26.x
node-version: "26"

steps:
- uses: actions/checkout@v4

Expand Down
8 changes: 7 additions & 1 deletion HISTORY.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
unreleased
===================
* fix: improve `limit` option validation (#698)
* Invalid `limit` values (e.g. unparseable strings or `NaN`) now throw instead of being silently ignored, which previously disabled size limit enforcement
* `null` and `undefined` fall back to the default 100kb limit

1.20.5 / 2026-04-24
===================
* refactor(json): simplify strict mode error string construction
* refactor(json): simplify strict mode error string construction
* fix: extended urlencoded parsing of arrays with >100 elements (#716)
* deps: qs@~6.15.1

Expand Down
10 changes: 7 additions & 3 deletions lib/types/json.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,15 +53,19 @@ var JSON_SYNTAX_REGEXP = /#+/g
function json (options) {
var opts = options || {}

var limit = typeof opts.limit !== 'number'
? bytes.parse(opts.limit || '100kb')
: opts.limit
var limit = typeof opts.limit === 'undefined' || opts.limit === null
? 102400 // 100kb default
: bytes.parse(opts.limit)
var inflate = opts.inflate !== false
var reviver = opts.reviver
var strict = opts.strict !== false
var type = opts.type || 'application/json'
var verify = opts.verify || false

if (limit === null) {
throw new TypeError('option limit "' + String(opts.limit) + '" is invalid')
}

if (verify !== false && typeof verify !== 'function') {
throw new TypeError('option verify must be function')
}
Expand Down
10 changes: 7 additions & 3 deletions lib/types/raw.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,16 @@ function raw (options) {
var opts = options || {}

var inflate = opts.inflate !== false
var limit = typeof opts.limit !== 'number'
? bytes.parse(opts.limit || '100kb')
: opts.limit
var limit = typeof opts.limit === 'undefined' || opts.limit === null
? 102400 // 100kb default
: bytes.parse(opts.limit)
var type = opts.type || 'application/octet-stream'
var verify = opts.verify || false

if (limit === null) {
throw new TypeError('option limit "' + String(opts.limit) + '" is invalid')
}

if (verify !== false && typeof verify !== 'function') {
throw new TypeError('option verify must be function')
}
Expand Down
10 changes: 7 additions & 3 deletions lib/types/text.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,16 @@ function text (options) {

var defaultCharset = opts.defaultCharset || 'utf-8'
var inflate = opts.inflate !== false
var limit = typeof opts.limit !== 'number'
? bytes.parse(opts.limit || '100kb')
: opts.limit
var limit = typeof opts.limit === 'undefined' || opts.limit === null
? 102400 // 100kb default
: bytes.parse(opts.limit)
var type = opts.type || 'text/plain'
var verify = opts.verify || false

if (limit === null) {
throw new TypeError('option limit "' + String(opts.limit) + '" is invalid')
}

if (verify !== false && typeof verify !== 'function') {
throw new TypeError('option verify must be function')
}
Expand Down
10 changes: 7 additions & 3 deletions lib/types/urlencoded.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,16 @@ function urlencoded (options) {

var extended = opts.extended !== false
var inflate = opts.inflate !== false
var limit = typeof opts.limit !== 'number'
? bytes.parse(opts.limit || '100kb')
: opts.limit
var limit = typeof opts.limit === 'undefined' || opts.limit === null
? 102400 // 100kb default
: bytes.parse(opts.limit)
var type = opts.type || 'application/x-www-form-urlencoded'
var verify = opts.verify || false

if (limit === null) {
throw new TypeError('option limit "' + String(opts.limit) + '" is invalid')
}

if (verify !== false && typeof verify !== 'function') {
throw new TypeError('option verify must be function')
}
Expand Down
30 changes: 30 additions & 0 deletions test/json.js
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,36 @@ describe('bodyParser.json()', function () {
})

describe('with limit option', function () {
it('should throw an error for an invalid string limit', function () {
assert.throws(function () {
bodyParser.json({ limit: 'invalid' })
}, /option limit "invalid" is invalid/)
assert.throws(function () {
bodyParser.json({ limit: '' })
}, /option limit "" is invalid/)
})

it('should throw an error for a NaN limit', function () {
assert.throws(function () {
bodyParser.json({ limit: NaN })
}, /option limit "NaN" is invalid/)
})

it('should throw an error for a boolean limit', function () {
assert.throws(function () {
bodyParser.json({ limit: true })
}, /option limit "true" is invalid/)
assert.throws(function () {
bodyParser.json({ limit: false })
}, /option limit "false" is invalid/)
})

it('should throw an error for an object limit', function () {
assert.throws(function () {
bodyParser.json({ limit: { foo: 'bar' } })
}, /option limit "\[object Object\]" is invalid/)
})

it('should 413 when over limit with Content-Length', function (done) {
var buf = Buffer.alloc(1024, '.')
request(createServer({ limit: '1kb' }))
Expand Down
30 changes: 30 additions & 0 deletions test/raw.js
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,36 @@ describe('bodyParser.raw()', function () {
})

describe('with limit option', function () {
it('should throw an error for an invalid string limit', function () {
assert.throws(function () {
bodyParser.raw({ limit: 'invalid' })
}, /option limit "invalid" is invalid/)
assert.throws(function () {
bodyParser.raw({ limit: '' })
}, /option limit "" is invalid/)
})

it('should throw an error for a NaN limit', function () {
assert.throws(function () {
bodyParser.raw({ limit: NaN })
}, /option limit "NaN" is invalid/)
})

it('should throw an error for a boolean limit', function () {
assert.throws(function () {
bodyParser.raw({ limit: true })
}, /option limit "true" is invalid/)
assert.throws(function () {
bodyParser.raw({ limit: false })
}, /option limit "false" is invalid/)
})

it('should throw an error for an object limit', function () {
assert.throws(function () {
bodyParser.raw({ limit: { foo: 'bar' } })
}, /option limit "\[object Object\]" is invalid/)
})

it('should 413 when over limit with Content-Length', function (done) {
var buf = Buffer.alloc(1028, '.')
var server = createServer({ limit: '1kb' })
Expand Down
30 changes: 30 additions & 0 deletions test/text.js
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,36 @@ describe('bodyParser.text()', function () {
})

describe('with limit option', function () {
it('should throw an error for an invalid string limit', function () {
assert.throws(function () {
bodyParser.text({ limit: 'invalid' })
}, /option limit "invalid" is invalid/)
assert.throws(function () {
bodyParser.text({ limit: '' })
}, /option limit "" is invalid/)
})

it('should throw an error for a NaN limit', function () {
assert.throws(function () {
bodyParser.text({ limit: NaN })
}, /option limit "NaN" is invalid/)
})

it('should throw an error for a boolean limit', function () {
assert.throws(function () {
bodyParser.text({ limit: true })
}, /option limit "true" is invalid/)
assert.throws(function () {
bodyParser.text({ limit: false })
}, /option limit "false" is invalid/)
})

it('should throw an error for an object limit', function () {
assert.throws(function () {
bodyParser.text({ limit: { foo: 'bar' } })
}, /option limit "\[object Object\]" is invalid/)
})

it('should 413 when over limit with Content-Length', function (done) {
var buf = Buffer.alloc(1028, '.')
request(createServer({ limit: '1kb' }))
Expand Down
30 changes: 30 additions & 0 deletions test/urlencoded.js
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,36 @@ describe('bodyParser.urlencoded()', function () {
})

describe('with limit option', function () {
it('should throw an error for an invalid string limit', function () {
assert.throws(function () {
bodyParser.urlencoded({ limit: 'invalid' })
}, /option limit "invalid" is invalid/)
assert.throws(function () {
bodyParser.urlencoded({ limit: '' })
}, /option limit "" is invalid/)
})

it('should throw an error for a NaN limit', function () {
assert.throws(function () {
bodyParser.urlencoded({ limit: NaN })
}, /option limit "NaN" is invalid/)
})

it('should throw an error for a boolean limit', function () {
assert.throws(function () {
bodyParser.urlencoded({ limit: true })
}, /option limit "true" is invalid/)
assert.throws(function () {
bodyParser.urlencoded({ limit: false })
}, /option limit "false" is invalid/)
})

it('should throw an error for an object limit', function () {
assert.throws(function () {
bodyParser.urlencoded({ limit: { foo: 'bar' } })
}, /option limit "\[object Object\]" is invalid/)
})

it('should 413 when over limit with Content-Length', function (done) {
var buf = Buffer.alloc(1024, '.')
request(createServer({ limit: '1kb' }))
Expand Down
Loading