NoSQL Injection detection for MongoDB, Redis, CouchDB, and Elasticsearch
Scanned 9/12/2026
Install to Claude Code
npx -y skills add aibot88/sec_skill_store --skill sc-nosqli --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Sc Nosqli?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/aibot88-sc-nosqli)More formats (shields.io, HTML) on the badges page.
---
name: sc-nosqli
description: NoSQL Injection detection for MongoDB, Redis, CouchDB, and Elasticsearch
license: MIT
metadata:
category: security
version: "1.0.0"
---
# SC: NoSQL Injection
## Purpose
Detects NoSQL injection vulnerabilities where user-controlled input manipulates NoSQL database queries. Unlike SQL injection, NoSQL injection exploits operator injection, JSON structure manipulation, and JavaScript execution within query contexts. Covers MongoDB, Redis, CouchDB, DynamoDB, and Elasticsearch.
## Activation
Called by sc-orchestrator during Phase 2. Runs when NoSQL databases are detected in the architecture.
## Phase 1: Discovery
### File Patterns to Search
```
**/*.ts, **/*.js, **/*.py, **/*.php, **/*.java, **/*.go, **/*.cs,
**/models/*, **/controllers/*, **/services/*, **/repositories/*,
**/*mongo*, **/*redis*, **/*elastic*, **/*couch*, **/*dynamo*
```
### Keyword Patterns to Search
```
# MongoDB
"find(", "findOne(", "findOneAndUpdate(", "findOneAndDelete(",
"aggregate(", "updateOne(", "updateMany(", "deleteOne(", "deleteMany(",
"$where", "$regex", "$gt", "$gte", "$lt", "$lte", "$ne", "$in", "$nin",
"$or", "$and", "$not", "$exists", "$expr",
"MongoClient", "mongoose.model", "collection.find"
# Redis
"redis.get(", "redis.set(", "redis.eval(", "redis.send_command(",
"EVAL ", "EVALSHA", "redis.call("
# Elasticsearch
"client.search(", "client.index(", "query_string",
"script_score", "painless", "elasticsearch"
# CouchDB
"_find", "mango", "cloudant"
```
### Data Flow Tracing
**Sources:** HTTP request body (JSON), query parameters, headers, cookies
**Sinks:**
- MongoDB: `collection.find()`, `collection.findOne()`, `Model.find()`, `aggregate()` — when query object is constructed from user input
- Redis: `EVAL` with user input in script, `redis.send_command()` with dynamic commands
- Elasticsearch: `query_string` query with user input, `script` fields with user input
## Phase 2: Verification
### Exploitability Checklist
1. Can the attacker inject MongoDB operators (`$gt`, `$ne`, `$regex`, `$where`) into the query?
2. Can the attacker modify the query structure by injecting JSON keys?
3. Can the attacker inject JavaScript code into `$where` or `$function` expressions?
4. Is the request body parsed as JSON and passed directly to the database driver?
### Sanitization Check
1. Is input validated against expected types (string, number, ObjectId)?
2. Are MongoDB operators stripped from user input?
3. Is input sanitized using a library like `mongo-sanitize` or `express-mongo-sanitize`?
4. Is Mongoose schema validation enforced before query execution?
### Framework Protection Check
- **Mongoose with schema:** Schema validation prevents type confusion but NOT operator injection in `.find()` with raw objects
- **Prisma (MongoDB):** Prisma abstracts queries and prevents operator injection
- **Spring Data MongoDB:** `MongoTemplate` with `Criteria` API is safe; raw query strings are not
### MongoDB Operator Injection Example
```javascript
// VULNERABLE: User input directly in query object
app.post('/login', async (req, res) => {
const user = await User.findOne({
username: req.body.username,
password: req.body.password
});
});
// Attack: POST {"username":"admin","password":{"$ne":""}}
// This returns any user where password is not empty — bypasses auth
// SAFE: Validate input types
app.post('/login', async (req, res) => {
if (typeof req.body.username !== 'string' || typeof req.body.password !== 'string') {
return res.status(400).json({ error: 'Invalid input' });
}
const user = await User.findOne({
username: req.body.username,
password: req.body.password
});
});
```
### MongoDB $where Injection
```javascript
// VULNERABLE: User input in $where JavaScript expression
const results = await collection.find({
$where: `this.category == '${req.query.category}'`
});
// Attack: ?category=' || true || '
// Executes arbitrary JavaScript on the server
// SAFE: Use standard query operators
const results = await collection.find({
category: req.query.category
});
```
### Redis EVAL Injection
```python
# VULNERABLE: User input in Redis Lua script
script = f"return redis.call('get', '{user_input}')"
result = redis_client.eval(script, 0)
# SAFE: Use parameterized Redis commands
result = redis_client.get(user_input)
```
### Elasticsearch Query String Injection
```javascript
// VULNERABLE: User input in query_string
const results = await client.search({
query: {
query_string: {
query: req.query.search // User can inject Lucene syntax
}
}
});
// SAFE: Use match query instead
const results = await client.search({
query: {
match: {
content: req.query.search
}
}
});
```
## Severity Classification
- **Critical:** Authentication bypass via operator injection, or JavaScript execution via `$where`/`$function` with user input
- **High:** Data exfiltration through query manipulation, unauthorized access to other users' data
- **Medium:** Query manipulation with limited impact (e.g., bypassing filter conditions)
- **Low:** Information disclosure through error messages revealing database structure
## Output Format
### Finding: NOSQLI-{NNN}
- **Title:** NoSQL Injection in {function/endpoint}
- **Severity:** Critical | High | Medium | Low
- **Confidence:** 0-100
- **File:** file/path:line
- **Vulnerability Type:** CWE-943 (Improper Neutralization of Special Elements in Data Query Logic)
- **Description:** User input is passed directly into {database} query allowing operator injection.
- **Proof of Concept:** Attacker sends `{"$ne": ""}` as the {parameter} to bypass equality check.
- **Impact:** {Authentication bypass / data exfiltration / unauthorized data modification}
- **Remediation:** Validate input types, use `mongo-sanitize`, or use an ORM that prevents operator injection.
- **References:** https://cwe.mitre.org/data/definitions/943.html, https://owasp.org/www-project-web-security-testing-guide/latest/4-Web_Application_Security_Testing/07-Input_Validation_Testing/05.6-Testing_for_NoSQL_Injection
## Common False Positives
1. **Prisma/Mongoose with strict schema** — typed models prevent operator injection when schema validation is enforced
2. **Hardcoded queries** — query objects built entirely from constants, not user input
3. **Internal service-to-service calls** — query parameters come from trusted internal services, not HTTP requests
4. **Admin/seed scripts** — database operations in setup scripts that don't handle user input
5. **Aggregation pipelines with static structure** — pipeline stages defined in code with only values from user input (parameterized)
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!