no-operator-injection
Detects MongoDB operator injection attacks where user input is passed directly as query values, allowing attackers to...
Keywords: NoSQL injection, CWE-943, MongoDB, $ne, $gt, $or, operator injection, security
Detects MongoDB operator injection attacks where user input is passed directly as query values, allowing attackers to inject operators like $ne, $gt, $or to bypass authentication or exfiltrate data.
⚠️ This rule errors by default in the recommended config.
Quick Summary
| Aspect | Details |
|---|---|
| CWE Reference | CWE-943 (NoSQL Injection) |
| OWASP | A03:2021 - Injection |
| Severity | Critical (CVSS: 9.1) |
| Category | Security |
| ESLint MCP | ✅ Optimized for AI assistant integration |
Value & investment case
Why this rule pays for itself. Framework:
cicd-impact/philosophy.md.
| Dimension | Value |
|---|---|
| CWE | CWE-943 — Improper Neutralization of Special Elements in Data Query Logic (NoSQL injection, CVSS 9.1) |
| Feedback-loop tier | Editor / pre-commit (sub-second) — cheapest layer per the feedback-loop hierarchy |
| Defensive-layer leverage | ~10× cheaper than unit-test · ~1,000× cheaper than production rollback · 10,000+× cheaper than customer disclosure (cost-ratio anchors) |
| Niche relevance | Critical: fintech, healthtech, B2B SaaS (any MongoDB-backed multi-tenant app) · High: marketplaces, infra/devtools · Medium: B2C |
| Investor-frame impact | NoSQL operator injection ($ne, $gt, $or injection) → authentication bypass + data exfiltration. The MongoDB-specific equivalent of SQL injection; same class of disclosure event. Catch at lint-time prevents the entire attack family. |
Read also: philosophy.md §investor-frame · niche-presets.json · analyzer-evaluation-framework.md
Rule Details
This rule specifically targets operator injection - a subset of NoSQL injection where attackers submit objects with MongoDB operators instead of expected primitive values.
Attack Scenario
// Expected: { username: "john", password: "secret123" }
// Attacker sends: { username: "admin", password: { "$ne": "" } }
// This query:
db.users.findOne({ username: req.body.username, password: req.body.password });
// Becomes:
db.users.findOne({ username: 'admin', password: { $ne: '' } });
// Matches admin user with ANY non-empty password - authentication bypass!❌ Incorrect
const filter = { $ne: req.body.value };✅ Correct
// Force value comparison with $eq
User.findOne({ email: { $eq: req.body.email } });
// Cast to primitive type
User.findOne({ email: String(req.body.email) });
// Validate input is not an object
if (typeof req.body.email !== 'string') throw new Error('Invalid input');
User.findOne({ email: req.body.email });Known False Negatives
Object Spread
// ❌ NOT DETECTED - spreads entire body into query
User.findOne({ ...req.body });Dynamic Property Access
// ❌ NOT DETECTED - dynamic key assignment
const query = {};
query[field] = value;Aggregation Pipelines
// ❌ NOT DETECTED - complex pipeline structure
User.aggregate([{ $match: req.body.filter }]);When Not To Use It
- When using Mongoose schema with strict validation that rejects object values
- When all input is validated through a strict JSON schema (e.g., Zod, Joi)
- In test files with intentionally vulnerable patterns
Related Rules
- no-unsafe-query - General unsafe query detection
- no-unsafe-where - $where operator detection
References
Did this rule catch something? Star the repo to get new CWE coverage as we ship it — or follow the AI-code-security benchmarks behind these rules.