One body sanitiser, not two - #818
Merged
Merged
Conversation
Correcting myself. api/app.js has had a working NoSQL guard on the body all along - `req.body` is an ordinary property, unlike the query getter that #811 found had been a silent no-op since Express 5. I did not check that before adding src/middleware/no-mongo-operators.js. I built a bare Express app inside my own test, watched an operator reach the handler there, and reported it as this application's behaviour. It was not: the scaffold had no sanitiser because I had not put one in it. The middleware still earns its place - it removes __proto__, constructor and prototype, which the old walk never did, bounds its own walk against a structure built to be walked, and logs a count and a path rather than a string the caller chose. But the body was being stripped twice, and two implementations of one promise is how the two drift: a rule added to one and not the other reads as covered and is not. So the duplicate goes and the dedicated one stays. `sanitize` remains for the QUERY STRING, which is its own problem and was not running at all until #811. The wiring test from #811 pinned the removed line by its exact text. Its comment says what it was defending - "the body half never needed it and still must not be broken" - and that guarantee is unchanged, so the assertion now checks it rather than the line: something strips the body, before any route. Changed across sessions on purpose, and said so in the test. The new test asserts against the REAL app rather than a scaffold, which is what the earlier one should have done.
Contributor
|
Merged to Try it at https://develop.posnic.io, or run it yourself: git fetch origin develop && git checkout develop
npm install && npm --prefix api install
npm run dev # then http://localhost:3000When you have tested it, say what you did and what happened, and set Reporting that something is broken is as useful as fixing it. It is |
This was referenced Sep 16, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Correcting myself.
api/app.jshas had a working NoSQL guard on the body all along.req.bodyis an ordinary property, unlike the query getter that #811 found had been a silent no-op since Express 5.I did not check that before adding
src/middleware/no-mongo-operators.jsin #812. I built a bare Express app inside my own test, watched an operator reach the handler there, and reported it as this application's behaviour. It was not. The scaffold had no sanitiser because I had not put one in it, and #811's own comment says the body half was never affected.The middleware still earns its place
It does three things the old walk does not:
__proto__,constructorandprototypesanitizeis unbounded recursion over caller-supplied structureWhat it should not do is strip the body a second time. Two implementations of one promise is how the two drift: a rule added to one and not the other reads as covered and is not. That is the argument I made about the unanswered-orders sweeper in #807, and it applies to me here.
So the duplicate goes, the dedicated one stays, and
sanitizekeeps the query string, which is its own problem and was not running at all until #811.I changed a test from another session
#811's wiring check pinned the removed line by its exact text:
Its comment says what it was defending, and that guarantee is unchanged - the body is still stripped, before any route, by the dedicated middleware. So the assertion now checks the guarantee instead of the line, and fails if the middleware is ever removed. The change is explained in the test itself so whoever wrote it sees why.
And the new test uses the real app
require('../../../app.js')and walk the actual middleware chain, rather than a scaffold built in the test. That is what the earlier one should have done, and it is the whole lesson here.Checks
check-locally.jsall 7 passOrdering
Release #816 is already open and carries #812 as it was. This one is a follow-up, so it needs its own release after. Nothing is broken in between - the body is sanitised twice, which is wasteful rather than wrong.