Open-Source Wikis

/

Express

/

Security

expressjs/express

Security

Active contributors: dougwilson, ulisesgascon, wesleytodd

Express runs on the public internet by default. The framework's small footprint puts most of the security responsibility on application code and on the dependencies it integrates. This page lists what the project itself does and the patterns the codebase uses to stay safe.

Reporting vulnerabilities

Use the security policy and GitHub's private vulnerability reporting workflow. Do not open public issues. The Readme.md has the canonical link.

Repository-level controls

  • CodeQL.github/workflows/codeql.yml runs GitHub's static analysis on every push and pull request.
  • OpenSSF Scorecard.github/workflows/scorecard.yml posts a supply-chain hygiene score; the badge is displayed at the top of Readme.md.
  • Dependabot.github/dependabot.yml keeps Actions and runtime dependencies bumped. Roughly half of the last 50 commits to master are dependency bumps (see By the numbers).
  • persist-credentials: false — Every workflow checkout uses this to avoid leaking the GITHUB_TOKEN to subsequent steps.
  • Pinned action SHAs — Actions in CI workflows are referenced by commit SHA with a version comment (e.g., actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2). This is enforced manually but is consistent.

CVEs in recent history

Date Affected Notes
2024-10-08 cookie semver lock Express 5.0.1: bumped cookie-signature to address CVE-2024-47764.
2025-12-01 (rejected) CVE-2024-51999 Express 5.2.0 attempted a fix; 5.2.1 reverted it on the same day after the CVE was rejected and the fix proved to be a breaking change to the extended query parser. See History.md.
2026-XX (master) qs minimum version fix: bump qs minimum to ^6.14.2 for CVE-2026-2391 lands as commit 925a1dff on master, ahead of the next release.

The full history of security-related changes is preserved in History.md.

Built-in security-relevant behaviour

X-Powered-By header

app.handle in lib/application.js sets X-Powered-By: Express on every response when the 'x-powered-by' setting is enabled (the default). To remove it:

app.disable('x-powered-by');

res.jsonp Rosetta Flash mitigation

res.jsonp (lib/response.js) prepends /**/ to its output and sets X-Content-Type-Options: nosniff. This prevents browsers from misinterpreting the response as a Flash file (Rosetta Flash attack class). It also escapes \u2028 and \u2029 in the body to avoid breaking out of JSON in older JS parsers.

The callback name from the query string is sanitised against /[^\[\]\w$.]/g so only \w, $, ., [, and ] survive.

res.redirect body

res.redirect builds an HTML body that includes a <title> and <body> (added in master post-5.2). The URL is HTML-escaped via the escape-html package before insertion. The Location header itself is encoded by encodeurl.

res.status strictness

Express 5 made res.status strict: only integers in [100, 999] are accepted. Out-of-range or non-integer values throw. This eliminates a class of bugs where a typo (res.status('200'), res.status(2000)) would silently propagate.

Trust proxy

The 'trust proxy' setting decides whether X-Forwarded-* headers are honoured. Default is false — Express does not trust forwarded headers unless you opt in. Misconfiguring this is a common cause of bypassed rate-limiting or IP-restricted endpoints. Configure it to match the count of trusted hops in front of your app, or to a CIDR list.

Cookies

  • res.cookie requires req.secret for signed: true. There is no fallback default secret.
  • res.clearCookie ignores user-provided maxAge/expires (Express 5) so a stale config can't accidentally re-extend a "cleared" cookie.
  • Always set httpOnly and secure for session-related cookies in production. The framework does not do this for you.

Body parsing limits

express.json and friends accept a limit option. The default is '100kb' (set inside body-parser). Large file uploads should not flow through these parsers — use a dedicated multipart library or a streaming approach.

Application-level recommendations

The expressjs/expressjs.com documentation has a dedicated security guide (Security Best Practices). High-level recommendations include:

  • Use helmet to set sane HTTP security headers.
  • Use HTTPS in production (terminate at a reverse proxy or https.createServer).
  • Don't disable etag unless you have a reason — caches help mitigate certain DoS patterns.
  • Validate user input — Express does not sanitise request bodies for you.
  • Pin or audit your qs/body-parser major versions for prototype-pollution risk.

Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.

Security – Express wiki | Factory