Skip to content

feat!: support Express 5 #201

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

Peppershaker
Copy link

@Peppershaker Peppershaker commented Apr 8, 2025

Breaking Change

The middleware now requires that you set the query parser to "extended" with:

expressApp.set('query parser', 'extended')

in order to correctly parse and sanitize nested query parameters.

Express 5 Query Parsing Changes

From Express v5 docs.

  • The default query parser has shifted from qs to Node’s native querystring parser.
  • You can disable query parsing by setting the value to false.
  • Alternatively, you may choose the "simple" or "extended" parser, or supply a custom query string parsing function:
    • Simple: Based on Node’s native querystring module.
    • Extended: Based on the qs library.
    • Custom: Receives the raw query string and must return an object mapping keys to their corresponding values.

req.query

In Express 5, the req.query object is now read-only.

Design Considerations

1. Injection Protection for Nested Queries

Option 1: Log a warning on application startup.

  • No need to inspect the current query parser; simply warn that the "simple" parser is potentially unsafe and could expose users to nested operator injection attacks.

Option 2: Require a reference to the Express app object.

  • Actively verify that the "extended" query parser is in use, and throw an error if it is not.

Option 3: Do nothing.

  • Similar approach to bodyParser.urlencoded({ extended: true }).
  • The user will be responsible for determining the security risk.
  • Unparsed nested queries are not valid MongoDB queries anyway.

2. Handling the Read-Only Nature of req.query

Option 1: Maintain the behavior of the middleware as a query parser (similar to v2).

  • This allows for easier migration but violates Express 5’s expectation that req.query is read-only.
  • The middleware will forcibly overwrite req.query using Object.defineProperty.

Option 2: Separate the concerns by splitting functionality into a query parser and a sanitization middleware.

  • Use the qs query parser for parsing and let this package handle sanitization of query parameters.
  • A separate middleware processes the body, params, and headers.
  • This approach adheres more closely to Express 5’s philosophy of a read-only req.query, but since Express only allows a single query parser, users must either implement a custom two-step solution (using qs for parsing followed by sanitization) or rely on our built-in helper functions. This may increase dependency complexity and blur the boundaries of the package’s responsibility.

Recommendation

  • Injection Protection for Nested Queries: Option 1c (Do nothing).
  • Handling req.query Read-Only Nature: Option 2a (Maintain the behavior of the middleware as a query parser).

Additionally, explain the security implications in your documentation.


@Peppershaker Peppershaker force-pushed the feat/express-5-migration branch 2 times, most recently from 26bec2e to dbe3bd7 Compare April 8, 2025 04:57
BREAKING CHANGE: Must use expressApp.set('query parser', 'extended') to
parse and sanitize nested query params
@Peppershaker Peppershaker force-pushed the feat/express-5-migration branch from dbe3bd7 to 61c495e Compare April 8, 2025 04:58
@alexanderfink
Copy link
Collaborator

@Peppershaker According to the comments in this issue #200 the maintianer is looking for someone to take over this repo.

@alexanderfink alexanderfink self-assigned this May 27, 2025
@alexanderfink alexanderfink requested a review from Copilot May 27, 2025 09:40
Copy link

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

Adds support for Express 5 by requiring the “extended” query parser and handling req.query sanitization, updates dependencies and docs, and bumps the major version.

  • Introduce explicit req.query sanitization with Object.defineProperty to respect Express 5’s read‐only queries.
  • Update tests to set the query parser to “extended” for nested query tests.
  • Bump to v3.0.0, update dependencies to Express 5, and refresh documentation.

Reviewed Changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 4 comments.

File Description
test.js Added app.set('query parser', 'extended') in each test setup
package.json Bumped version to 3.0.0; moved Express into dependencies; updated dev deps
index.js Removed 'query' from the main loop and added separate handling for req.query
README.md Updated for Express 5, added notes about setting the query parser and readonly req.query
Comments suppressed due to low confidence (1)

test.js:23

  • Add tests to cover behavior when the query parser is not set to 'extended', ensuring the middleware fails gracefully or documents the expected outcome.
app.set('query parser', 'extended');

Comment on lines +48 to +49
"dependencies": {
"express": "^5.1.0"
Copy link
Preview

Copilot AI May 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider moving Express to peerDependencies instead of dependencies to avoid bundling a separate Express version and let hosting apps control the Express version.

Suggested change
"dependencies": {
"express": "^5.1.0"
"peerDependencies": {
"express": "^5.1.0"
},
"devDependencies": {
"@types/express": "^5.0.1",
"body-parser": "^1.19.1",
"chai": "^4.5.0",
"eslint": "^8.6.0",
"mocha": "^9.2.2",
"prettier": "^2.5.1",
"supertest": "^7.1.0",
"tsd": "^0.19.1",
"express": "^5.1.0"

Copilot uses AI. Check for mistakes.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Peppershaker Is there a reason why you added the dependencies section?

Repository owner deleted a comment from Copilot AI May 27, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants