feat: add CORS-aware ETag modes and configurable query parser options #6908
+716
−15
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Overview
This PR introduces two independent enhancements to Express.js that address long-standing issues with CDN caching and query string handling.
Changes Included
1. CORS-Aware ETag Generation (Fixes #5986)
Adds new ETag modes that include response headers in ETag calculation to prevent cache conflicts when serving content to multiple origins through CDNs.
New ETag modes:
'weak-cors': Weak ETag including Access-Control-Allow-Origin header'strong-cors': Strong ETag including Access-Control-Allow-Origin headerProblem solved: CDNs returning 304 Not Modified responses that omit CORS headers, causing browsers to apply cached CORS headers from different origins, resulting in CORS errors.
Usage:
`app.set('etag', 'weak-cors');
app.use(function(req, res) {
res.set('Access-Control-Allow-Origin', req.get('Origin'));
res.send('content');
});`
Implementation:
createETagGeneratorto acceptincludeHeadersoptionres.send()to pass response headers to ETag function2. Configurable Query Parser Options (Fixes #5878)
Adds ability to configure
qslibrary options when using the extended query parser, addressing silent parameter truncation and providing better security controls.New API:
app.set('query parser', 'extended'); app.set('query parser options', { parameterLimit: 5000, // Increase from default 1000 arrayLimit: 50, // Increase from default 20 depth: 10, // Increase from default 5 allowPrototypes: false // Prevent prototype pollution });Problem solved: Query strings exceeding the default 1000 parameter limit resulted in silent data loss. The default
allowPrototypes: truesetting poses a prototype pollution security risk.Implementation:
compileQueryParsernow accepts optionalqsOptionsparametercreateExtendedQueryParserfactory function replacesparseExtendedQueryStringapp.set('query parser options')triggers parser recompilationBackward Compatibility
Both features maintain full backward compatibility:
Test Coverage
test/utils.js+ 10 integration tests intest/res.send.cors.jstest/req.query.options.jsSecurity Considerations
The query parser feature helps prevent prototype pollution attacks by allowing developers to set
allowPrototypes: false. The default remainstruefor backward compatibility, but documentation encourages the secure option.