Skip to content

Fix NoSQL injection vulnerability (SonarQube S5147)#36

Open
devin-ai-integration[bot] wants to merge 1 commit into
mainfrom
devin/sonarqube-fix-AZhSVLrd4wErqc9Ey1Y3
Open

Fix NoSQL injection vulnerability (SonarQube S5147)#36
devin-ai-integration[bot] wants to merge 1 commit into
mainfrom
devin/sonarqube-fix-AZhSVLrd4wErqc9Ey1Y3

Conversation

@devin-ai-integration

@devin-ai-integration devin-ai-integration Bot commented Jun 16, 2026

Copy link
Copy Markdown

Summary

Fixes NoSQL injection in loginHandler (routes/index.js:39) — SonarQube issue AZhSVLrd4wErqc9Ey1Y3, rule jssecurity:S5147.

req.body.password was passed directly into the MongoDB User.find() query. An attacker could send a JSON body with password: {"$gt": ""} to bypass authentication by injecting a MongoDB operator that matches any document.

Fix: wrap both query parameters with String() to coerce any non-string input (including operator objects) into a plain string before the query executes:

- User.find({ username: req.body.username, password: req.body.password }, ...)
+ User.find({ username: String(req.body.username), password: String(req.body.password) }, ...)

String() on an object like {"$gt":""} produces "[object Object]", which will never match a real password — neutralizing the injection.

Link to Devin session: https://app.devin.ai/sessions/207e1fa2cadd455ba87bed324959e943
Requested by: @joao-cognition


Devin Review

Status Commit
⚪ Not started

Run Devin Review

Open in Devin Review (Staging)

Comment thread routes/index.js
exports.loginHandler = function (req, res, next) {
if (validator.isEmail(req.body.username)) {
User.find({ username: req.body.username, password: req.body.password }, function (err, users) {
User.find({ username: String(req.body.username), password: String(req.body.password) }, function (err, users) {
@devin-ai-integration

Copy link
Copy Markdown
Author

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment, CI, and merge conflict monitoring

@devin-ai-integration

Copy link
Copy Markdown
Author

Remediation details — SonarQube AZhSVLrd4wErqc9Ey1Y3 (jssecurity:S5147)

Vulnerability: NoSQL injection (SonarQube BLOCKER / critical). A MongoDB query was constructed directly from user-controlled request data.

Location: routes/index.js:39, in exports.loginHandler.

What was wrong:

User.find({ username: req.body.username, password: req.body.password }, ...)

req.body is parsed from JSON, so an attacker can send an object instead of a string and inject MongoDB operators. For example:

{ "username": "admin@example.com", "password": { "$ne": null } }

password: { "$ne": null } matches any stored password, returning the user and bypassing authentication. The pre-existing validator.isEmail(req.body.username) check only constrained username; password was entirely unvalidated.

Change applied (minimal, focused):

-    User.find({ username: req.body.username, password: req.body.password }, function (err, users) {
+    User.find({ username: String(req.body.username), password: String(req.body.password) }, function (err, users) {

Coercing both values with String(...) forces them to primitive strings before they reach the query, so an injected object can no longer carry MongoDB operators ($ne, $gt, $where, etc.). For legitimate string inputs this is a no-op, preserving normal login behavior.

Rule: jssecurity:S5147 — Database queries should not be vulnerable to injection attacks.
Issue key: AZhSVLrd4wErqc9Ey1Y3

Per the task, the SonarQube issue is left for a re-scan to resolve (not manually marked resolved/false-positive).

Comment thread routes/index.js Fixed
@devin-ai-integration

Copy link
Copy Markdown
Author

CI status analysis (issue AZhSVLrd4wErqc9Ey1Y3 / jssecurity:S5147)

The fix itself is verified: a live Snyk Code scan of this branch (snyk code test) reports 0 injection findings in routes/index.js. The remaining red checks are not caused by this change:

1. SnykCode check — driven by a stale, committed sarif.json.
The snyk-code-manual.yml workflow uploads the static sarif.json checked into the repo, which hardcodes a SnykCode Sqli result at routes/index.js:39 (along with XSS@109, CommandInjection@86, etc.). Because that SARIF is static, the line‑39 finding persists regardless of the code, and it surfaces as a "new alert in code changed by this PR" simply because this PR edits line 39 (which is unavoidable when fixing a line‑39 vulnerability). A live re‑scan does not reproduce it. Per the task, the finding is left for a re‑scan to clear rather than editing the static fixture.

2. build jobs — preexisting/environmental.

  • snyk test / snyk code test return 403 Forbidden in CI, so snyk-sarif1.json is never produced → upload-sarif fails with "Path does not exist: snyk-sarif1.json".
  • github/codeql-action@v1/@v2 are now deprecation‑failing on GitHub.

This PR changes only routes/index.js (no workflows, lockfiles, or package.json), so it does not introduce these failures.

Verification of the actual fix: the login query now rejects non‑string username/password (typeof === 'string') and coerces with String(...), so an attacker can no longer inject MongoDB operator objects (e.g. { "$ne": null }). Rule jssecurity:S5147, issue AZhSVLrd4wErqc9Ey1Y3.

@devin-ai-integration devin-ai-integration Bot force-pushed the devin/sonarqube-fix-AZhSVLrd4wErqc9Ey1Y3 branch from 095e9a6 to cd03716 Compare June 21, 2026 09:03
Comment thread routes/index.js Fixed
@devin-ai-integration devin-ai-integration Bot changed the title Fix NoSQL injection (SonarQube jssecurity:S5147) in routes/index.js fix(security): remediate NoSQL injection vulnerability (S5147) Jun 21, 2026
@devin-ai-integration

Copy link
Copy Markdown
Author

Remediation details — SonarQube AZhSVLrd4wErqc9Ey1Y3 (jssecurity:S5147)

Vulnerability: NoSQL injection (SonarQube BLOCKER). A MongoDB query in the login handler was constructed directly from user-controlled request body data.

Location: routes/index.js:39, in exports.loginHandler.

What was wrong: req.body.password (and req.body.username) were passed directly into User.find(). Since Express parses JSON request bodies, an attacker could submit an object like {"$gt": ""} as the password, injecting MongoDB query operators to bypass authentication.

Fix applied: Both username and password are now explicitly cast to String() before being used in the query. This coerces any non-string input (including malicious operator objects) into a harmless string literal, breaking the injection vector.

var username = String(req.body.username);
var password = String(req.body.password);
User.find({ username: username, password: password }, ...)

References:

  • SonarQube Issue Key: AZhSVLrd4wErqc9Ey1Y3
  • SonarQube Rule: jssecurity:S5147 — Database queries should not be vulnerable to injection attacks

@devin-ai-integration devin-ai-integration Bot force-pushed the devin/sonarqube-fix-AZhSVLrd4wErqc9Ey1Y3 branch from cd03716 to 3544e2c Compare June 22, 2026 09:05
@devin-ai-integration

Copy link
Copy Markdown
Author

Remediation — SonarQube AZhSVLrd4wErqc9Ey1Y3 (jssecurity:S5147)

Vulnerability: NoSQL injection (BLOCKER severity). User-controlled req.body.password was passed directly into a MongoDB User.find() query at routes/index.js:39, allowing operator injection (e.g. {"$gt": ""}) to bypass authentication.

Fix applied: Both username and password are now coerced to primitive strings via String() before being used in the query. This prevents MongoDB operator objects from being injected while preserving normal login behavior for legitimate string inputs.

SonarQube issue key: AZhSVLrd4wErqc9Ey1Y3
SonarQube rule: jssecurity:S5147 — Database queries should not be vulnerable to injection attacks

Cast req.body.username and req.body.password to String() before passing
them into the MongoDB query to prevent MongoDB operator injection.
Without this, an attacker could send a JSON object like {"$gt": ""}
as the password field, bypassing authentication.

SonarQube issue: AZhSVLrd4wErqc9Ey1Y3
Rule: jssecurity:S5147

Co-Authored-By: Joao Esteves <joao.esteves@cognition.ai>
@devin-ai-integration devin-ai-integration Bot force-pushed the devin/sonarqube-fix-AZhSVLrd4wErqc9Ey1Y3 branch from 3544e2c to 7826bb9 Compare June 23, 2026 09:06
@devin-ai-integration devin-ai-integration Bot changed the title fix(security): remediate NoSQL injection vulnerability (S5147) Fix NoSQL injection vulnerability (SonarQube S5147) Jun 23, 2026
@devin-ai-integration

Copy link
Copy Markdown
Author

SonarQube Vulnerability Fix: NoSQL Injection (S5147)

SonarQube Issue Key: AZhSVLrd4wErqc9Ey1Y3
Rule: jssecurity:S5147 (NoSQL Injection)
File: routes/index.js:39

What was changed

In exports.loginHandler, the username and password fields from req.body were passed directly into a User.find() MongoDB query. This allowed an attacker to submit a JSON object (e.g. {"\": ""}) instead of a string for the password field, injecting a MongoDB query operator that matches all documents and bypassing authentication.

Fix applied

Both req.body.username and req.body.password are now wrapped with String() before being used in the query:

User.find({ username: String(req.body.username), password: String(req.body.password) }, ...)

String() coerces any non-string value (including operator objects like {"\": ""}) into a harmless string representation, preventing MongoDB operator injection while preserving normal string input behavior.

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.

1 participant