From soundcheck
Detects NoSQL injection risks in MongoDB, Elasticsearch queries with user input. Enforces primitive type checks, blocks $where/$expr, prevents raw param passthrough.
npx claudepluginhub thejefflarson/soundcheck --plugin soundcheckThis skill uses the workspace's default tool permissions.
Protects against NoSQL injection where user input manipulates query operators or
Detects and exploits NoSQL injection vulnerabilities in MongoDB, CouchDB, and other NoSQL databases to demonstrate authentication bypass, data extraction, and unauthorized access during web penetration testing and API security reviews.
Detects and exploits NoSQL injection in MongoDB/CouchDB via JSON payloads for auth bypass and data extraction during web app pentesting and API security audits.
Detects and exploits NoSQL injection vulnerabilities in MongoDB and CouchDB for authentication bypass, data extraction during web app pentests and bug bounties.
Share bugs, ideas, or general feedback.
Protects against NoSQL injection where user input manipulates query operators or
structure. Unlike SQL injection, NoSQL injection exploits operator injection
($gt, $ne, $regex) and JavaScript execution in database engines. Exploitation
leads to authentication bypass, data exfiltration, and denial of service.
db.users.find({user: req.body.user, pass: req.body.pass}) — {pass: {$ne: ""}} bypasses authcollection.find({"$where": f"this.name == '{user_input}'"}) — JS injection in $wheredb.collection.find(JSON.parse(req.query.filter)) — arbitrary query operator injectionModel.find(req.query) — Mongoose passes raw query params as operatorsFlag the vulnerable code and explain the risk. Then suggest a fix that establishes these properties:
{pass: {$ne: ""}} auth bypass works because the
deserialized JSON was allowed to be an object; type-coercing it to a string
turns $ne into a literal that can't match.$where, $expr, and $function never receive user-supplied values.
These operators accept JavaScript or expression strings that the database
engine evaluates; with user input in them, the database is an interpreter
running attacker code.mass-assignment
skill for ORM-side details).Anchor — shape, not implementation:
require(isinstance(username, str)) # reject objects / arrays
user = db.users.find_one({"username": username}) # primitive, not operator
# never: db.users.find({"$where": f"this.name == '{user_input}'"})
# never: collection.find(req.body) # operators smuggle in
$where, $expr, and $function are never used with user-supplied values