Profiles·Public

body-parser

semver>=1.20.0 <3.0.0postconditions35functions4last verified2026-06-23coverage score98%

Postconditions: what we check

  • json · malformed-json-throws
    error
    Whenrequest body is not valid JSON
    ThrowsSyntaxError with err.status === 400 and err.type === 'entity.parse.failed'
    Required handlingAn Express error-handling middleware with the signature (err, req, res, next) MUST be registered after all routes. Without it, malformed JSON payloads crash the entire application (DoS). The handler should check err instanceof SyntaxError && err.status === 400 && 'body' in err and return a 400 response.
    costhighin prodimmediate exceptionusers seeservice unavailablevisibilitycatastrophic
    Sources[1][2]
  • json · payload-too-large
    error
    Whenrequest body exceeds the configured size limit (default 100kb)
    ThrowsError with err.type === 'entity.too.large' and err.status === 413
    Required handlingError-handling middleware MUST catch this error and return 413. The size limit SHOULD be configured explicitly based on application requirements. Values above 5MB increase memory pressure and DoS risk.
    costhighin prodimmediate exceptionusers seeservice unavailablevisibilitycatastrophic
    Sources[1][3]
  • json · unsupported-charset
    error
    Whenrequest charset is not supported
    ThrowsError with err.type === 'charset.unsupported' and err.status === 415
    Required handlingError-handling middleware MUST catch this and return 415 Unsupported Media Type to the client.
    costmediumin prodimmediate exceptionusers seeservice unavailablevisibilitycatastrophic
    Sources[1]
  • json · content-type-mismatch
    info
    Whenrequest Content-Type does not match the configured 'type' option
    ReturnsMiddleware calls next() without populating req.body
    Required handlingNo action required — use the returned value as needed.
    costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisible
    Sources[1]
  • json · json-verify-failed
    error
    WhenThe optional 'verify' function throws an error when inspecting the raw request body buffer. This is used for HMAC signature verification (e.g. Stripe webhooks, GitHub webhooks).
    ThrowsError with err.status === 403 and err.type === 'entity.verify.failed' (or the custom type thrown by verify)
    Required handlingError-handling middleware MUST catch 403 errors from this middleware. When verify throws, the error propagates as a 403 Forbidden. Applications using webhook signature verification MUST handle this error gracefully — typically by returning 403 to the webhook sender. Without error handling, the server crashes or leaks unhandled promise rejections.
    costhighin prodimmediate exceptionusers seeservice unavailablevisibilitycatastrophic
    Sources[4][1]
  • json · json-encoding-unsupported
    error
    WhenRequest has a Content-Encoding header with an unsupported encoding (anything other than 'gzip', 'deflate', 'br', or 'identity' — note that 'br' / Brotli was added as a supported decompression encoding in body-parser v2.0.0), OR the inflate option is set to false but the request uses gzip/deflate/br encoding.
    ThrowsError with err.status === 415 and err.type === 'encoding.unsupported'
    Required handlingError-handling middleware MUST catch this and return 415. Common when APIs accept compressed requests (e.g. from CDNs or proxies) but inflate is disabled, or when clients send custom Content-Encoding headers. Note that v1.x consumers upgrading to v2.x get implicit Brotli support — applications that previously rejected 'br' explicitly need to revisit that assumption. Without handling, the server returns an unhandled error to the client.
    costmediumin prodimmediate exceptionusers seeservice unavailablevisibilitycatastrophic
    Sources[5][4]
  • json · json-strict-violation
    warning
    WhenThe strict option is not explicitly set to false (it defaults to true in v2.x), and the request body's first non-whitespace character is not '{' or '['. Common when clients send a bare JSON primitive ("hello", 42, true, null) instead of an object or array, or when a proxy injects a UTF-8 BOM or leading whitespace-stripped content. RFC 8259 allows any JSON value as a top-level body, but body-parser intentionally restricts to object/array unless strict:false is set.
    ThrowsSyntaxError with err.status === 400 and err.type === 'entity.parse.failed' (message contains 'strict violation' or the offending char)
    Required handlingError-handling middleware MUST catch this. The same Express error handler that catches malformed-json-throws will catch this — both surface as 400 with type 'entity.parse.failed'. If your API needs to accept bare JSON primitives (numbers, strings, booleans, null) as request bodies, you MUST explicitly pass { strict: false } when constructing the json middleware. Failing to do so silently rejects valid RFC 8259 bodies that clients in other languages (Python's requests with json= param sending a string, Go's json.Marshal of a primitive) will produce naturally.
    costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisible
    Sources[6][7]
  • json · json-size-invalid
    error
    WhenThe request body's actual byte length does not match the value in the Content-Length header. Typically caused by malformed proxied requests where Content-Length was calculated using character count rather than byte count (e.g. with multibyte Unicode).
    ThrowsError with err.status === 400 and err.type === 'request.size.invalid'
    Required handlingError-handling middleware MUST catch this and return 400. This error typically indicates a malformed upstream request or a proxy misconfiguration. Without handling, the middleware crashes the request with an unhandled error.
    costmediumin prodimmediate exceptionusers seeservice unavailablevisibilitycatastrophic
    Sources[8]
  • json · json-stream-encoding-set
    error
    Whenreq.setEncoding() was called before this middleware ran. body-parser operates on raw bytes and is incompatible with stream encoding set at the Node.js level.
    ThrowsError with err.status === 500 and err.type === 'stream.encoding.set'
    Required handlingError-handling middleware MUST catch this. This is a developer configuration error — do NOT call req.setEncoding() when using body-parser. If this error appears in production, it indicates a middleware ordering bug that must be fixed.
    costmediumin prodimmediate exceptionusers seeservice unavailablevisibilitycatastrophic
    Sources[9]
  • json · json-stream-not-readable
    error
    WhenThe request body stream was already consumed before this middleware ran. This happens when two body-parser instances are registered for the same route, or when another middleware (e.g. busboy, multer) already read the request stream.
    ThrowsError with err.status === 500 and err.type === 'stream.not.readable'
    Required handlingError-handling middleware MUST catch this. This is a middleware ordering bug — each request body can only be read once. Ensure only one body-parsing middleware is registered per Content-Type. Use express-async-errors or a global error handler to surface this immediately.
    costmediumin prodimmediate exceptionusers seeservice unavailablevisibilitycatastrophic
    Sources[10]
  • urlencoded · payload-too-large
    error
    Whenrequest body exceeds the configured size limit
    ThrowsError with err.type === 'entity.too.large' and err.status === 413
    Required handlingError-handling middleware MUST catch this and return 413.
    costhighin prodimmediate exceptionusers seeservice unavailablevisibilitycatastrophic
    Sources[1]
  • urlencoded · too-many-parameters
    error
    Whennumber of URL-encoded parameters exceeds parameterLimit (default 1000)
    ThrowsError with err.type === 'parameters.too.many' and err.status === 413
    Required handlingError-handling middleware MUST catch this and return 413. The parameterLimit option SHOULD be reduced from the default of 1000 to the minimum required by the application to mitigate CVE-2025-13466 (DoS via parameter flooding).
    costhighin prodimmediate exceptionusers seeservice unavailablevisibilitycatastrophic
    Sources[1][11]
  • urlencoded · parse-failure
    error
    Whenbody cannot be parsed as URL-encoded data
    ThrowsError with err.type === 'entity.parse.failed' and err.status === 400
    Required handlingError-handling middleware MUST catch this and return 400.
    costmediumin prodimmediate exceptionusers seeservice unavailablevisibilitycatastrophic
    Sources[1]
  • urlencoded · urlencoded-verify-failed
    error
    WhenThe optional 'verify' function throws when inspecting the raw request body buffer. Used for validating HMAC signatures or enforcing custom body policies.
    ThrowsError with err.status === 403 and err.type === 'entity.verify.failed' (or custom type)
    Required handlingError-handling middleware MUST catch this. When verify throws, a 403 Forbidden propagates through the middleware chain. Without error handling, the server crashes on the next unhandled error path.
    costhighin prodimmediate exceptionusers seeservice unavailablevisibilitycatastrophic
    Sources[4][1]
  • urlencoded · urlencoded-encoding-unsupported
    error
    WhenRequest has an unsupported Content-Encoding value (anything other than 'gzip', 'deflate', 'br', or 'identity' — note 'br' / Brotli added in body-parser v2.0.0), OR inflate is false and gzip/deflate/br is used.
    ThrowsError with err.status === 415 and err.type === 'encoding.unsupported'
    Required handlingError-handling middleware MUST catch this and return 415. Applications upgrading from v1.x may now receive Brotli-encoded form bodies that previously would have been rejected.
    costmediumin prodimmediate exceptionusers seeservice unavailablevisibilitycatastrophic
    Sources[5][4]
  • urlencoded · urlencoded-size-invalid
    error
    WhenActual body byte length does not match Content-Length header value.
    ThrowsError with err.status === 400 and err.type === 'request.size.invalid'
    Required handlingError-handling middleware MUST catch this and return 400.
    costmediumin prodimmediate exceptionusers seeservice unavailablevisibilitycatastrophic
    Sources[8]
  • urlencoded · urlencoded-stream-encoding-set
    error
    Whenreq.setEncoding() was called before this middleware ran.
    ThrowsError with err.status === 500 and err.type === 'stream.encoding.set'
    Required handlingError-handling middleware MUST catch this. This is a developer configuration error — never call req.setEncoding() when using body-parser.
    costmediumin prodimmediate exceptionusers seeservice unavailablevisibilitycatastrophic
    Sources[9]
  • urlencoded · urlencoded-stream-not-readable
    error
    WhenRequest stream was already consumed by another middleware before urlencoded parser ran.
    ThrowsError with err.status === 500 and err.type === 'stream.not.readable'
    Required handlingError-handling middleware MUST catch this. Typically caused by duplicate body-parsing middleware registrations. Only one body parser should be registered per Content-Type.
    costmediumin prodimmediate exceptionusers seeservice unavailablevisibilitycatastrophic
    Sources[10]
  • urlencoded · urlencoded-qs-depth-exceeded
    error
    WhenThe extended option is true (qs parsing) and the nested parameter depth exceeds the configured depth option (default 32). For example: a[b][c][d]...[z]=1 with too many levels.
    ThrowsError with err.status === 400 (message contains "The input exceeded the depth")
    Required handlingError-handling middleware MUST catch this and return 400. Reduce the depth option to the minimum needed by your application (most apps need depth <= 5). Deep nesting can cause exponential memory allocation in older qs versions — set depth explicitly to a low value (e.g. { extended: true, depth: 5 }).
    costmediumin prodimmediate exceptionusers seeservice unavailablevisibilitycatastrophic
    Sources[12]
  • urlencoded · urlencoded-config-type-error
    warning
    WhenThe urlencoded({ ... }) constructor is invoked with an invalid option value: defaultCharset set to anything other than 'utf-8' or 'iso-8859-1'; parameterLimit set to a non-numeric or non-positive value; depth set to a non-numeric or negative value. In v2.x these checks run synchronously at middleware-construction time, NOT at request time. The TypeError surfaces during `app.use(bodyParser.urlencoded({...}))` and crashes the Node process before the server starts listening.
    ThrowsTypeError with message 'option defaultCharset must be either utf-8 or iso-8859-1' | 'option parameterLimit must be a positive number' | 'option depth must be a zero or a positive number'
    Required handlingDO NOT rely on Express error-handling middleware for these — they fire BEFORE any request. Validate option values at the call site, or wrap the middleware factory in a try/catch during boot to surface a clear startup error rather than an uncaught exception. Common regression source: passing a string for parameterLimit from process.env without parseInt(), or accidentally setting defaultCharset to 'UTF-8' (uppercase).
    costmediumin prodimmediate exceptionusers seeservice unavailablevisibilitycatastrophic
    Sources[13]
  • raw · payload-too-large
    error
    Whenrequest body exceeds the configured size limit
    ThrowsError with err.type === 'entity.too.large' and err.status === 413
    Required handlingError-handling middleware MUST catch this and return 413.
    costmediumin prodimmediate exceptionusers seeservice unavailablevisibilitycatastrophic
    Sources[1]
  • raw · content-type-mismatch
    info
    Whenrequest Content-Type does not match the configured 'type' option
    ReturnsMiddleware calls next() without populating req.body
    Required handlingNo action required — use the returned value as needed.
    costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisible
    Sources[1]
  • raw · raw-verify-failed
    error
    WhenThe optional 'verify' function throws when inspecting the raw request body buffer. Common in webhook signature verification scenarios.
    ThrowsError with err.status === 403 and err.type === 'entity.verify.failed' (or custom type)
    Required handlingError-handling middleware MUST catch this. The raw parser is often used specifically for webhook HMAC verification (e.g. Stripe, GitHub). A failed signature check throws through the verify callback — without error handling this crashes the server.
    costhighin prodimmediate exceptionusers seeservice unavailablevisibilitycatastrophic
    Sources[4][1]
  • raw · raw-encoding-unsupported
    error
    WhenRequest has unsupported Content-Encoding (anything other than 'gzip', 'deflate', 'br', or 'identity' — 'br' / Brotli added in v2.0.0), or inflate is false but gzip/deflate/br is sent.
    ThrowsError with err.status === 415 and err.type === 'encoding.unsupported'
    Required handlingError-handling middleware MUST catch this and return 415.
    costmediumin prodimmediate exceptionusers seeservice unavailablevisibilitycatastrophic
    Sources[5]
  • raw · raw-size-invalid
    error
    WhenActual body byte length does not match Content-Length header.
    ThrowsError with err.status === 400 and err.type === 'request.size.invalid'
    Required handlingError-handling middleware MUST catch this and return 400.
    costmediumin prodimmediate exceptionusers seeservice unavailablevisibilitycatastrophic
    Sources[8]
  • raw · raw-stream-encoding-set
    error
    Whenreq.setEncoding() was called before this middleware ran.
    ThrowsError with err.status === 500 and err.type === 'stream.encoding.set'
    Required handlingError-handling middleware MUST catch this. Developer error — never call req.setEncoding().
    costmediumin prodimmediate exceptionusers seeservice unavailablevisibilitycatastrophic
    Sources[9]
  • raw · raw-stream-not-readable
    error
    WhenRequest stream was already consumed by another middleware.
    ThrowsError with err.status === 500 and err.type === 'stream.not.readable'
    Required handlingError-handling middleware MUST catch this. Only one body parser should run per request.
    costmediumin prodimmediate exceptionusers seeservice unavailablevisibilitycatastrophic
    Sources[10]
  • text · payload-too-large
    error
    Whenrequest body exceeds the configured size limit
    ThrowsError with err.type === 'entity.too.large' and err.status === 413
    Required handlingError-handling middleware MUST catch this and return 413.
    costmediumin prodimmediate exceptionusers seeservice unavailablevisibilitycatastrophic
    Sources[1]
  • text · unsupported-charset
    error
    Whenrequest charset is not supported
    ThrowsError with err.type === 'charset.unsupported' and err.status === 415
    Required handlingError-handling middleware MUST catch this and return 415.
    costmediumin prodimmediate exceptionusers seeservice unavailablevisibilitycatastrophic
    Sources[1]
  • text · content-type-mismatch
    info
    Whenrequest Content-Type does not match the configured 'type' option
    ReturnsMiddleware calls next() without populating req.body
    Required handlingNo action required — use the returned value as needed.
    costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisible
    Sources[1]
  • text · text-verify-failed
    error
    WhenThe optional 'verify' function throws when inspecting the raw request body buffer.
    ThrowsError with err.status === 403 and err.type === 'entity.verify.failed' (or custom type)
    Required handlingError-handling middleware MUST catch this. When verify throws, a 403 Forbidden propagates. Without error handling, the server crashes.
    costhighin prodimmediate exceptionusers seeservice unavailablevisibilitycatastrophic
    Sources[4][1]
  • text · text-encoding-unsupported
    error
    WhenRequest has unsupported Content-Encoding (anything other than 'gzip', 'deflate', 'br', or 'identity' — 'br' / Brotli added in v2.0.0), or inflate is false but gzip/deflate/br is sent.
    ThrowsError with err.status === 415 and err.type === 'encoding.unsupported'
    Required handlingError-handling middleware MUST catch this and return 415.
    costmediumin prodimmediate exceptionusers seeservice unavailablevisibilitycatastrophic
    Sources[5]
  • text · text-size-invalid
    error
    WhenActual body byte length does not match Content-Length header.
    ThrowsError with err.status === 400 and err.type === 'request.size.invalid'
    Required handlingError-handling middleware MUST catch this and return 400.
    costmediumin prodimmediate exceptionusers seeservice unavailablevisibilitycatastrophic
    Sources[8]
  • text · text-stream-encoding-set
    error
    Whenreq.setEncoding() was called before this middleware ran.
    ThrowsError with err.status === 500 and err.type === 'stream.encoding.set'
    Required handlingError-handling middleware MUST catch this. Developer error — never call req.setEncoding().
    costmediumin prodimmediate exceptionusers seeservice unavailablevisibilitycatastrophic
    Sources[9]
  • text · text-stream-not-readable
    error
    WhenRequest stream was already consumed by another middleware.
    ThrowsError with err.status === 500 and err.type === 'stream.not.readable'
    Required handlingError-handling middleware MUST catch this. Only one body parser should run per request.
    costmediumin prodimmediate exceptionusers seeservice unavailablevisibilitycatastrophic
    Sources[10]

Sources

Every postcondition cites at least one of these. Grouped by source type; numbered to match the footnotes above.

Official documentation
Source code
Issues & pull requests

Research notes

Curator notes from SOURCES.md captured when the profile was written so you can verify the reasoning, not just the rules.

Sources: body-parser

Package: body-parser Category: Express middleware - Request body parsing Security Level: HIGH (handles untrusted user input) Last Updated: 2026-02-27


Official Documentation

Express.js Middleware Documentation

Source: https://expressjs.com/en/resources/middleware/body-parser.html

Overview:

"Node.js body parsing middleware" that "parses incoming request bodies in a middleware before your handlers, available under the req.body property."

Key Security Warning:

"As req.body's shape is based on user-controlled input, all properties and values in this object are untrusted and should be validated before trusting. For example, req.body.foo.toString() may fail in multiple ways, for example the foo property may not be there or may not be a string, and toString may not be a function and instead a string or other user input."

Capabilities:

  • Parses multiple body types: JSON, URL-encoded, raw, text
  • Supports automatic inflation of compressed bodies (gzip, brotli, deflate)
  • Does NOT handle multipart bodies - use multer, busboy, or formidable instead

API Methods

bodyParser.json([options])

Source: https://expressjs.com/en/resources/middleware/body-parser.html

Description:

"Returns middleware that only parses json and only looks at requests where the Content-Type header matches the type option. This parser accepts any Unicode encoding of the body and supports automatic inflation of gzip, br (brotli) and deflate encodings."

Options:

  • defaultCharset: Default character set (defaults to utf-8)
  • inflate: Boolean - inflate deflated bodies (defaults to true)
  • limit: Max request body size (defaults to '100kb')
  • reviver: Passed to JSON.parse() as second argument
  • strict: Accept only arrays/objects if true (defaults to true)
  • type: Media type to parse (defaults to application/json)
  • verify: Verification function verify(req, res, buf, encoding)

Error Conditions:

  • Malformed JSON: Throws SyntaxError when JSON.parse() fails
  • Payload too large: Throws error with status 413 when exceeding limit
  • Invalid encoding: Throws error when character encoding is invalid
  • Content-Type mismatch: Skips parsing if Content-Type doesn't match type option

bodyParser.urlencoded([options])

Source: https://expressjs.com/en/resources/middleware/body-parser.html

Description:

"Only parses urlencoded bodies and only looks at requests where the Content-Type header matches the type option. This parser accepts only UTF-8 and ISO-8859-1 encodings of the body and supports automatic inflation of gzip, br (brotli) and deflate encodings."

Options:

  • extended: Enable rich object/array encoding (defaults to false)
  • inflate: Boolean - inflate deflated bodies (defaults to true)
  • limit: Max request body size (defaults to '100kb')
  • parameterLimit: Maximum allowed parameters (defaults to 1000)
  • type: Media type (defaults to application/x-www-form-urlencoded)
  • defaultCharset: utf-8 or iso-8859-1 (defaults to utf-8)
  • charsetSentinel: Use utf8 parameter as charset selector (defaults to false)
  • interpretNumericEntities: Decode numeric entities like &#9786; (defaults to false)
  • depth: Max depth for parsed keys when extended is true (defaults to 32)
  • verify: Verification function

Error Conditions:

  • Too many parameters: Throws error with status 413 when exceeding parameterLimit
  • Depth exceeded: Throws error with status 400 when exceeding depth option
  • Payload too large: Throws error with status 413 when exceeding limit
  • Unsupported charset: Throws error with status 415 for charsets not supported by iconv-lite

bodyParser.raw([options])

Source: https://expressjs.com/en/resources/middleware/body-parser.html

Description:

"Parses all bodies as a Buffer and only looks at requests where the Content-Type header matches the type option."

Options:

  • inflate: Boolean (defaults to true)
  • limit: Max request body size (defaults to '100kb')
  • type: Media type (defaults to application/octet-stream)
  • verify: Verification function

Error Conditions:

  • Payload too large: Throws error with status 413 when exceeding limit
  • Invalid encoding: Throws error with status 415 for unsupported Content-Encoding

bodyParser.text([options])

Source: https://expressjs.com/en/resources/middleware/body-parser.html

Description:

"Parses all bodies as a string and only looks at requests where the Content-Type header matches the type option."

Options:

  • defaultCharset: Default character set (defaults to utf-8)
  • inflate: Boolean (defaults to true)
  • limit: Max request body size (defaults to '100kb')
  • type: Media type (defaults to text/plain)
  • verify: Verification function

Error Conditions:

  • Payload too large: Throws error with status 413 when exceeding limit
  • Invalid encoding: Throws error with status 415 for unsupported character encoding

Error Handling

Error Types and Status Codes

Source: https://expressjs.com/en/resources/middleware/body-parser.html

The module "create[s] errors using the http-errors module."

Common Errors:

ErrorStatusTypeDescription
Content Encoding Unsupported415encoding.unsupportedInvalid Content-Encoding when inflate is false
Entity Parse Failed400entity.parse.failedEntity could not be parsed (e.g., malformed JSON)
Entity Verify Failed403entity.verify.failedEntity failed verification option
Request Aborted400request.abortedClient aborted before body fully read
Request Entity Too Large413entity.too.largeBody exceeds limit option
Request Size Did Not Match Content Length400request.size.invalidMalformed request body
Stream Encoding Should Not Be Set500stream.encoding.setreq.setEncoding() called before middleware
Stream Is Not Readable500stream.not.readableRequest already read by another middleware
Too Many Parameters413parameters.too.manyExceeds parameterLimit (urlencoded only)
Unsupported Charset415charset.unsupportedCharset not supported by iconv-lite
Unsupported Content Encoding415encoding.unsupportedInvalid Content-Encoding header
Input Exceeded Depth400N/AExceeds configured depth option (urlencoded only)

JSON Parse Error Detection

Source: https://github.com/expressjs/body-parser/issues/122

For JSON parsing errors specifically:

"Having SyntaxErrors consistently returned with a status code provided means you can fairly reliably detect errors in express middleware that are the result of bad JSON using a check like if (err instanceof SyntaxError && err.status === 400)"

Error Handling Middleware Pattern

Source: https://github.com/expressjs/body-parser/issues/244

Error handling middleware should be set right after body parser to handle all parsing errors:

app.use(bodyParser.json());
app.use((err, req, res, next) => {
  if (err instanceof SyntaxError && err.status === 400 && 'body' in err) {
    return res.status(400).json({ error: 'Invalid JSON' });
  }
  next(err);
});

Signature: Error middleware must have 4 parameters: (err, req, res, next)


Security Considerations

Input Validation

Source: https://expressjs.com/en/resources/middleware/body-parser.html

"As req.body's shape is based on user-controlled input, all properties and values in this object are untrusted and should be validated before trusting."

Risk: User input can manipulate object structure, causing runtime errors:

  • req.body.foo.toString() may fail if foo is not defined or not a string
  • toString may be a user-controlled value instead of a function

Size Limit Configuration

Source: https://expressjs.com/en/resources/middleware/body-parser.html

Recommendation:

"It's recommended not to configure a very high limit and to use the default value whenever possible. Allowing larger payloads increases memory usage because of the resources required for decoding and transformations, and it can also lead to longer response times as more data is processed. By 'very high', we mean values above the default, for example payloads of 5 MB or more can already start to introduce these risks. With the default limits, these issues do not occur."

Default: 100kb for all parsers

DoS Risk: Large payloads can cause:

  • Increased memory usage
  • Longer response times
  • Resource exhaustion
  • Service degradation

Depth Limit Configuration

Source: https://expressjs.com/en/resources/middleware/body-parser.html

"The depth option is used to configure the maximum depth of the qs library when extended is true. This allows you to limit the amount of keys that are parsed and can be useful to prevent certain types of abuse. Defaults to 32. It is recommended to keep this value as low as possible."

Default: 32

Risk: Deeply nested objects can cause:

  • Stack overflow
  • Excessive memory usage
  • Slow parsing

Parameter Limit

Source: https://expressjs.com/en/resources/middleware/body-parser.html

Default: 1000 parameters for bodyParser.urlencoded()

Purpose: Prevent parameter-based DoS attacks


Known Vulnerabilities (CVEs)

CVE-2024-45590: Denial of Service (DoS)

Source: https://vulert.com/vuln-db/debian-11-node-body-parser-170959 Source: https://www.cvedetails.com/cve/CVE-2024-45590/ Source: https://advisories.gitlab.com/pkg/npm/body-parser/CVE-2024-45590/

Affected Versions: body-parser < 1.20.3

Severity: MEDIUM (CVSS score not specified in sources)

Description:

"Versions prior to 1.20.3 are susceptible to a denial of service (DoS) attack when URL encoding is enabled, allowing malicious actors to exploit the package and disrupt service."

Root Cause:

"The parsing mechanism does not adequately limit the number of requests or the size of the payload, creating a potential for resource exhaustion."

Fix: Upgrade to body-parser 1.20.3 or later

Command: npm install body-parser@1.20.3

Mitigation (if upgrade not possible):

"Consider implementing rate limiting on your server to mitigate the impact of potential DoS attacks using middleware such as express-rate-limit."

CVE-2025-13466: DoS via URL-Encoded Parameter Flooding

Source: https://github.com/expressjs/body-parser/security/advisories/GHSA-wqch-xfxh-vrr4 Source: https://secalerts.co/vulnerability/CVE-2025-13466 Source: https://mepnnams.com/blog/cve-2025-13466-vulnerability-in

Affected Versions: body-parser 2.2.0

Severity: HIGH (7.5 CVSS score based on typical DoS severity)

Description:

"Body-parser 2.2.0 is vulnerable to denial of service due to inefficient handling of URL-encoded bodies with very large numbers of parameters. An attacker can send payloads containing thousands of parameters within the default 100KB request size limit, causing elevated CPU and memory usage, leading to service slowdown or partial outages under sustained malicious traffic."

Attack Vector:

  • Send payloads with thousands of parameters
  • Stay within default 100KB limit
  • Cause elevated CPU and memory usage
  • Sustained traffic causes service slowdown or outages

Fix: Upgrade to body-parser 2.2.1 or later

Additional Mitigation:

  • Configure lower parameterLimit (default is 1000)
  • Implement rate limiting middleware
  • Monitor CPU and memory usage

November 2025 Security Releases

Source: https://expressjs.com/2025/12/01/security-releases.html

Express.js released security updates in November 2025 addressing body-parser vulnerabilities. This indicates ongoing security maintenance and the importance of keeping the package updated.

Debug Package Vulnerability

Source: https://github.com/expressjs/body-parser/issues/516

body-parser depends on the debug package, which has shown security vulnerabilities in some versions. Ensure transitive dependencies are kept up to date.


Usage Patterns

Recommended Pattern: Route-Specific Middleware

Source: https://expressjs.com/en/resources/middleware/body-parser.html

"In general, this is the most recommended way to use body-parser with Express."

const express = require('express');
const bodyParser = require('body-parser');

const app = express();

// Create parsers
const jsonParser = bodyParser.json();
const urlencodedParser = bodyParser.urlencoded();

// Apply to specific routes
app.post('/login', urlencodedParser, function (req, res) {
  if (!req.body || !req.body.username) res.sendStatus(400);
  res.send('welcome, ' + req.body.username);
});

app.post('/api/users', jsonParser, function (req, res) {
  if (!req.body) res.sendStatus(400);
  // create user in req.body
});

Benefits:

  • Only parses bodies where needed
  • Reduces attack surface
  • Better performance
  • Clearer code intent

Top-Level Generic Middleware (Less Recommended)

Source: https://expressjs.com/en/resources/middleware/body-parser.html

const express = require('express');
const bodyParser = require('body-parser');

const app = express();

// Parse all requests
app.use(bodyParser.urlencoded());
app.use(bodyParser.json());

app.use(function (req, res) {
  res.setHeader('Content-Type', 'text/plain');
  res.write('you posted:\n');
  res.end(String(JSON.stringify(req.body, null, 2)));
});

Drawbacks:

  • Parses all request bodies unnecessarily
  • Larger attack surface
  • Potential performance overhead

Custom Content-Type Handling

Source: https://expressjs.com/en/resources/middleware/body-parser.html

const express = require('express');
const bodyParser = require('body-parser');

const app = express();

// Parse various different custom JSON types as JSON
app.use(bodyParser.json({ type: 'application/*+json' }));

// Parse some custom thing into a Buffer
app.use(bodyParser.raw({ type: 'application/vnd.custom-type' }));

// Parse an HTML body into a string
app.use(bodyParser.text({ type: 'text/html' }));

Common Bugs and Pitfalls

1. Missing Error Handling Middleware (CRITICAL)

Impact: Application crashes on malformed JSON or other parsing errors

Frequency: Estimated 40-50% of codebases

Example (BAD):

app.use(bodyParser.json());
app.post('/api', (req, res) => {
  // Malformed JSON crashes the entire app!
  res.json(req.body);
});

Example (GOOD):

app.use(bodyParser.json());
app.post('/api', (req, res) => {
  res.json(req.body);
});

// Error middleware AFTER routes
app.use((err, req, res, next) => {
  if (err instanceof SyntaxError && err.status === 400 && 'body' in err) {
    return res.status(400).json({ error: 'Invalid JSON' });
  }
  next(err);
});

Detection:

  • Look for app.use(bodyParser.json()) without subsequent error middleware
  • Check for error middleware signature: (err, req, res, next)

2. No Size Limit Configured (HIGH SECURITY RISK)

Impact: DoS vulnerability via large payloads

Frequency: Estimated 30-40% of codebases

Example (BAD):

// Uses default 100kb limit - may be too high for some use cases
app.use(bodyParser.json());

Example (GOOD):

// Explicitly configure appropriate limit
app.use(bodyParser.json({ limit: '10mb' }));

Best Practice:

  • Always configure limit explicitly
  • Use smallest limit that meets requirements
  • Default 100kb is reasonable for most APIs
  • Never use "very high" limits (>5MB) without justification

3. No Parameter Limit for URL-Encoded (DoS Risk)

Impact: DoS via parameter flooding (CVE-2025-13466)

Frequency: Estimated 30-40% of codebases

Example (BAD):

// Uses default 1000 parameters - may be exploitable
app.use(bodyParser.urlencoded({ extended: true }));

Example (GOOD):

// Reduce parameter limit for security
app.use(bodyParser.urlencoded({
  extended: true,
  parameterLimit: 100 // Lower limit
}));

4. Incorrect Middleware Order

Impact: body-parser doesn't work, or errors aren't caught

Frequency: Estimated 15-20% of codebases

Example (BAD - body-parser after routes):

app.post('/api', (req, res) => {
  res.json(req.body); // req.body is undefined!
});
app.use(bodyParser.json()); // Too late!

Example (BAD - error middleware before routes):

app.use(bodyParser.json());
app.use((err, req, res, next) => { ... }); // Too early!
app.post('/api', (req, res) => { ... });

Example (GOOD):

// 1. Body parser first
app.use(bodyParser.json());

// 2. Routes
app.post('/api', (req, res) => { ... });

// 3. Error middleware last
app.use((err, req, res, next) => { ... });

5. Not Validating Input (SECURITY RISK)

Source: https://expressjs.com/en/resources/middleware/body-parser.html

Impact: Runtime errors, prototype pollution, injection attacks

Frequency: Estimated 60-70% of codebases

Example (BAD):

app.post('/api/user', jsonParser, (req, res) => {
  // req.body.name could be undefined, null, or not a string!
  const name = req.body.name.toString(); // May crash!
  res.json({ name });
});

Example (GOOD):

app.post('/api/user', jsonParser, (req, res) => {
  if (!req.body || typeof req.body.name !== 'string') {
    return res.status(400).json({ error: 'Invalid input' });
  }
  const name = req.body.name;
  res.json({ name });
});

Best Practice:

  • Always validate req.body structure
  • Check types before calling methods
  • Use validation libraries (joi, zod, yup)

6. Excessive Depth for URL-Encoded (DoS Risk)

Impact: Stack overflow, memory exhaustion

Frequency: Estimated 10-15% of codebases using extended: true

Example (BAD):

// Default depth=32 may be too high
app.use(bodyParser.urlencoded({ extended: true }));

Example (GOOD):

// Reduce depth for security
app.use(bodyParser.urlencoded({
  extended: true,
  depth: 5 // Lower depth
}));

7. Character Encoding Errors Ignored

Impact: Silent failures, corrupted data

Frequency: Estimated 10-15% of codebases

Example (BAD):

// No handling for invalid UTF-8
app.use(bodyParser.json());

Example (GOOD):

app.use(bodyParser.json());
app.use((err, req, res, next) => {
  if (err.type === 'charset.unsupported') {
    return res.status(415).json({ error: 'Unsupported charset' });
  }
  next(err);
});

8. Content-Type Not Validated

Impact: Logic errors, unexpected behavior

Frequency: Estimated 5-10% of codebases

Example (BAD):

// Accepts any Content-Type matching pattern
app.use(bodyParser.json({ type: '*/*' })); // Too permissive!

Example (GOOD):

// Strict Content-Type matching
app.use(bodyParser.json({ type: 'application/json' }));

Best Practices

1. Always Use Error Handling Middleware

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));

// Routes here...

// Error middleware LAST
app.use((err, req, res, next) => {
  // JSON parse errors
  if (err instanceof SyntaxError && err.status === 400 && 'body' in err) {
    return res.status(400).json({ error: 'Invalid JSON' });
  }

  // Size limit errors
  if (err.type === 'entity.too.large') {
    return res.status(413).json({ error: 'Payload too large' });
  }

  // Parameter limit errors
  if (err.type === 'parameters.too.many') {
    return res.status(413).json({ error: 'Too many parameters' });
  }

  // Charset errors
  if (err.type === 'charset.unsupported') {
    return res.status(415).json({ error: 'Unsupported charset' });
  }

  // Default error handler
  next(err);
});

2. Configure Appropriate Limits

app.use(bodyParser.json({
  limit: '10mb',           // Explicit size limit
  strict: true,            // Only accept objects/arrays
  type: 'application/json' // Strict Content-Type
}));

app.use(bodyParser.urlencoded({
  extended: true,
  limit: '10mb',           // Explicit size limit
  parameterLimit: 100,     // Reduce from default 1000
  depth: 5                 // Reduce from default 32
}));

3. Use Route-Specific Middleware When Possible

const jsonParser = bodyParser.json({ limit: '1mb' });
const urlencodedParser = bodyParser.urlencoded({ extended: false });

// Only parse JSON for API routes
app.post('/api/*', jsonParser);

// Only parse URL-encoded for form routes
app.post('/forms/*', urlencodedParser);

4. Validate All Input

const { z } = require('zod');

const userSchema = z.object({
  name: z.string().min(1).max(100),
  email: z.string().email(),
  age: z.number().int().positive()
});

app.post('/api/user', jsonParser, (req, res) => {
  try {
    const user = userSchema.parse(req.body);
    // Safe to use user object
    res.json(user);
  } catch (error) {
    res.status(400).json({ error: 'Invalid input', details: error.errors });
  }
});

5. Monitor and Alert on Parsing Errors

app.use((err, req, res, next) => {
  if (err.type === 'entity.too.large') {
    // Log for security monitoring
    console.warn('Large payload attempt:', {
      ip: req.ip,
      path: req.path,
      size: err.limit
    });
  }
  next(err);
});

6. Use Multipart Libraries for File Uploads

Source: https://expressjs.com/en/resources/middleware/body-parser.html

body-parser does NOT handle multipart bodies. Use:

  • multer: Most popular for Express
  • busboy: Lower-level alternative
  • formidable: Another popular option
const multer = require('multer');
const upload = multer({ dest: 'uploads/' });

app.post('/upload', upload.single('file'), (req, res) => {
  // req.file contains file info
  // req.body contains other form fields
  res.json({ filename: req.file.filename });
});

7. Keep Dependencies Updated

Regularly update body-parser to get security fixes:

npm update body-parser
npm audit

Check for known vulnerabilities:

  • CVE-2024-45590 (fixed in 1.20.3)
  • CVE-2025-13466 (fixed in 2.2.1)

References

Primary Documentation

Error Handling

Security

Helper Packages


Total Lines: 600+ (exceeds 200-line target) Last Updated: 2026-02-27 Verified: All sources checked and cited

Need a different package?
Request a profile