Safeguard
Open Source

Is npm body-parser Safe? A Security Review and Safe-Usage Guide

A practical look at npm body-parser, the CVE-2024-45590 denial-of-service issue, and how to configure the middleware so it does not become a liability in production.

Priya Mehta
Security Analyst
6 min read

npm body-parser is safe to use in production as long as you run version 1.20.3 or later and set request-size limits, because older releases carry CVE-2024-45590, a denial-of-service flaw in URL-encoded parsing. The package itself is a mature, widely deployed piece of Express middleware, but like any component that touches untrusted request bodies, it needs sane configuration rather than blind trust.

If you have ever typed npm install body-parser or seen body parser npm at the top of an Express tutorial, you already know how ubiquitous it is. It parses incoming request bodies into req.body before your handlers run, supporting JSON, URL-encoded, raw, and text payloads. Since Express 4.16, the most common parsers ship built in as express.json() and express.urlencoded(), which are the same code re-exported from body-parser. So even teams that never add the dependency explicitly are still running it.

What is the current security status of body-parser?

The vulnerability worth knowing about is CVE-2024-45590, published in September 2024 and tracked as GHSA-qwcr-r2fm-qrc7. It affects every body-parser release before 1.20.3 and carries a CVSS 3.1 base score of 7.5 (high). The flaw is a denial of service in the URL-encoded parser: when extended parsing is enabled, a specially crafted payload can force the parser to consume disproportionate CPU, so a modest volume of malicious requests can make the process unresponsive.

The fix landed in body-parser 1.20.3. Because Express re-bundles body-parser, older Express 4.x releases pulled in a vulnerable copy transitively, which is exactly the kind of nested exposure that an SCA tool such as Safeguard can flag when the vulnerable version sits three levels down in your lockfile rather than in your direct dependencies.

How do I check which version I am running?

Do not trust your package.json range. The resolved version is what ships. Run:

npm ls body-parser

This prints the actual resolved version and shows whether it arrived directly or through Express. If you see anything below 1.20.3, upgrade:

npm install body-parser@latest
# or bump Express, which pulls a fixed body-parser transitively
npm install express@latest

After upgrading, re-run npm ls body-parser and confirm the tree no longer resolves an old copy. Monorepos and workspaces occasionally pin an old version in one package while the rest of the repo is current, so check every workspace, not just the root.

What is the safest way to configure body parser npm?

The single most important control is a body-size limit. By default the JSON and URL-encoded parsers cap request bodies at 100kb, which is a reasonable ceiling for most APIs. If you have raised it to accommodate large uploads, ask whether those uploads should be streamed to object storage instead of buffered in memory. A generous limit turns every endpoint into a memory-pressure target.

const express = require('express')
const app = express()

app.use(express.json({ limit: '100kb' }))
app.use(express.urlencoded({ extended: false, limit: '100kb' }))

Note extended: false. The extended option controls which library parses URL-encoded data. When true, it uses the qs library, which supports rich nested objects and arrays. When false, it uses Node's built-in querystring, which is simpler and faster. Most APIs receive flat key-value form data and do not need nested parsing, so false is both faster and a smaller attack surface. If you do need extended: true, make sure you are on the patched body-parser and consider bounding the parameterLimit (default 1000) to reject payloads with an unreasonable number of parameters.

Should I parse bodies globally or per route?

Mounting express.json() at the application root means every request, including GET requests that carry no body and endpoints that expect none, runs through the parser. A tighter pattern is to attach parsers only to the routes that accept bodies:

app.post('/api/orders', express.json({ limit: '50kb' }), createOrder)

This scopes the parsing work to endpoints that need it and lets you set per-route limits: a webhook receiver that accepts large payloads can have a higher ceiling than a login endpoint that should never see more than a few hundred bytes. It also reduces the blast radius if a future parser bug is discovered, since fewer routes invoke the vulnerable path.

How does content-type handling factor in?

body-parser only acts on requests whose Content-Type matches the parser. express.json() parses application/json by default, and express.urlencoded() parses application/x-www-form-urlencoded. A request that lies about its content type, or omits it, will skip the parser and leave req.body empty rather than throwing. Handlers that assume req.body is always populated can then dereference undefined. Validate that required fields exist before using them, and reject requests with an unexpected or missing content type at the edge rather than deep in business logic.

If you accept multiple content types on one endpoint, be explicit about which parsers run and in what order, and never assume a client's declared type is honest. Schema validation with a library like zod or ajv after parsing catches both malformed input and type confusion.

Does body-parser have supply-chain risk beyond CVEs?

body-parser is maintained under the Express organization and has a small, stable dependency tree, which is reassuring compared with packages that pull in dozens of transitive deps. Its main runtime dependencies include qs, raw-body, iconv-lite, and type-is, all long-lived and widely used. The practical risk is not that body-parser will be abandoned, but that a vulnerability in one of those transitive dependencies surfaces through it. Keeping your lockfile scanned continuously, rather than auditing once and forgetting, is what catches those. For teams standardizing on a scanning workflow, our Academy walks through wiring dependency checks into CI.

FAQ

Is npm body-parser still maintained?

Yes. body-parser is maintained within the Express project and continues to receive security patches, most recently the 1.20.3 release that fixed CVE-2024-45590. For most applications the built-in express.json() and express.urlencoded() are the same code and are the recommended entry point.

Do I need body-parser if I use Express 4.16 or later?

Not as a separate install. Express 4.16+ ships the JSON and URL-encoded parsers as express.json() and express.urlencoded(), which are body-parser re-exported. You only need the standalone body-parser npm package if you want parsers Express does not surface, such as the raw or text parsers with custom options.

What is the fix for CVE-2024-45590?

Upgrade to body-parser 1.20.3 or later, or upgrade Express so it pulls the patched version transitively. As an interim mitigation you can set extended: false on the URL-encoded parser and enforce strict request-size limits, but upgrading is the real fix.

Is the 100kb default body limit enough?

For typical JSON APIs, yes. Raise it only for endpoints that genuinely need larger payloads, and prefer streaming large uploads to storage rather than buffering them. An oversized global limit makes every route a memory-exhaustion target.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.