Add `express-mongo-sanitize` / operator stripping to the global middleware chain
@shobhamerabacha-star is already working on this.
Since Oct 9, 2026.
Assessment
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Newbie friendliness
- 35/100
Research direction
Start with the audit: check each query call in src/core/auth/auth.service.ts, traditional.strategy.ts, src/core/user/user.service.ts and src/search/search.service.ts to see whether its where value can come from unvalidated input. Then add app.use(mongoSanitize()) in src/main.ts before SanitizePipe and the validation pipe. Done means the audit is recorded in the issue, any unvalidated path is fixed or linked to its own bug, and a test shows a { "email": { "$ne": null } } payload is rejected while nested query parameters still work.
Written by the indexing model from the issue text.
Description
Problem
src/main.ts builds a global hardening chain — helmet (line 60), SanitizePipe (75), createGlobalValidationPipe() (76), CORS (80) — but nothing strips MongoDB/NoSQL query operators from incoming parameters.
express-mongo-sanitize@^2.2.0 is already in dependencies for exactly this, and is not imported anywhere in src/.
The relevant attack: an endpoint passing request parameters into a query builder can be given {"email": {"$ne": null}} instead of {"email": "..."}, turning an equality check into a match-anything. SanitizePipe (src/common/pipes/sanitize.pipe.ts) uses class-sanitizer, which strips HTML for XSS — it does not address operator injection.
The global ValidationPipe helps, because whitelist: true and forbidNonWhitelisted: true reject properties not on the DTO. But that protection only applies where a DTO class is used. Any handler taking a raw @Query() x: any or a plain object bypasses it entirely — and this codebase has such handlers (see the pagination-bounds and file-upload issues).
Why it matters
Whether this is exploitable today depends on whether any query path passes unvalidated input into a TypeORM or Elasticsearch query. That is exactly what needs verifying, because the answer determines severity:
- If all query paths use DTOs, this is defence in depth.
- If any pass raw objects through, it is a live authentication-bypass-class vulnerability — notably for login, where
{"email": {...}}could match any user.
Suggested Direction
- Audit first. For each repository
.find()/.findOne()/query-builder call, determine whether thewherevalue can come from an unvalidated request parameter. Prioritise auth (src/core/auth/auth.service.ts,traditional.strategy.ts), user lookup (src/core/user/user.service.ts), and search (src/search/search.service.ts, which passes a raw string into an Elasticsearchmulti_match). - If a vulnerable path exists, that is the real fix — it warrants its own high-priority bug issue, and this issue should link to it. Do not let the hardening issue substitute for the underlying bug.
- Add the middleware as defence in depth:
placed beforeapp.use(mongoSanitize());SanitizePipeand the validation pipe, insrc/main.ts. - Also check the search path specifically. Elasticsearch is not MongoDB, so
express-mongo-sanitizewill not cover it.search.service.tsbuilds amulti_matchquery from a raw string — verify the query DSL cannot be influenced by request structure, not just the string value.
Constraints
express-mongo-sanitizehad periods of unmaintained status — confirm 2.2.x is current and Express 5 compatible before relying on it.- Mutating
req.queryin place can surprise code that reads it later; test that legitimate nested query parameters still work. - Do not treat this as sufficient on its own. DTO validation with
whitelistis the primary control; this is a backstop.
Acceptance Criteria
- Every query-building path is audited, with the result recorded in the issue.
- Any path passing unvalidated input into a query is either fixed or linked to its own bug issue.
- Operator-stripping middleware is applied globally ahead of validation.
- A test asserts a payload like
{ "email": { "$ne": null } }is rejected. - Legitimate nested query parameters still work — assert this too.
- Dominant language
- TypeScript
- Stars
- 7
- Forks
- 55
- Avg merge
- 1d 17h
- Merged PRs (30d)
- 5
Getting set up
- Ships a Dockerfile or Docker Compose file
- Has a pull request template
- Read the contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from SourceXXL/alian_structure-api
-
good first issue help wanted security
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
SourceXXL/alian_structure-api#266 ·
-
Parallelize the cache-warming loop in `cache-warming.service.ts` — warmers run strictly sequentiallyPossibly taken @syntaxsuuvam-spec claimed this 5 days ago. Opengood first issue performance
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
SourceXXL/alian_structure-api#240 ·
-
documentation help wanted intermediate refactor
Difficulty 2/5 1-3 hours Newbie friendliness 70/100
SourceXXL/alian_structure-api#215 ·
-
good first issue refactor tooling
Difficulty 2/5 1-3 hours Newbie friendliness 80/100
SourceXXL/alian_structure-api#199 ·
-
help wanted intermediate refactor
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
SourceXXL/alian_structure-api#196 ·
All issues in SourceXXL/alian_structure-api
Similar issues
-
Difficulty 1/5 1-3 hours Newbie friendliness 75/100
siyuan-note/siyuan#20629 ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
Maintainers usually reply within 1 day
-
Volume eject does not refuse system, root or /home mountsPossibly taken @bernardopg claimed this today. Open
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
spacedriveapp/spacedrive#3159 ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
melgarafael/DeskcommCRM#3000 ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 70/100
callstackincubator/simlock#639 ·
Maintainers usually reply within 1 day