JavaScript NoSQL Injection prevention in MongoDB
Sushant's answer is not correct. You need to be aware of NoSQL injection in MongoDB.
Example (taken from here)
User.findOne({
"name" : req.params.name,
"password" : req.params.password
}, callback);
If req.params.password
is { $ne: 1 }
, the user will be retrieved without knowing the password ($ne
means not equals 1).
MongoDB Driver
You can use mongo-sanitize:
It will strip out any keys that start with '$' in the input, so you can pass it to MongoDB without worrying about malicious users overwriting.
var sanitize = require('mongo-sanitize');
var name = sanitize(req.params.name);
var password = sanitize(req.params.password);
User.findOne({
"name" : name,
"password" : password
}, callback);
Mongoose Driver
As it follows a schema, if the password is a string field, it will convert the object { $ne: 1 }
to string and no damage will be done. In this case, you don't need to sanitize, just remember to set a proper schema.
Although the post is obsolete, I'm answering.
I know three ways.
First: There is a multipurpose content-filter. Also provides MongoDB injection protection by filtering way.
Second: mongo-sanitize, Helper to sanitize mongodb queries against query selector injections.
Third: I'd seen over here this solution which can be applied for MongoDB too. It's really simple to implement. Only use built-in escape()
function of JavaScript. escape()
converts the string into ascii
code. $ne
is converted into %24ne
.
var privateKey = escape(req.params.privateKey);
App.findOne({ key: privateKey }, function (err, app) {
//do something here
}
In order to guard against query selector injections from a data object with unknown structure
Use mongo-sanitize to deeply sanitize via recursion:
const deepSanitize = (value) => {
if(Array.isArray(value)){
value.forEach(elm=>deepSanitize(elm))
}
if(typeof(value) === 'object' && value !== null){
Object.values(value).forEach((elm)=>{
deepSanitize(elm)
})
}
return sanitize(value)
}
For example with sanitize(req.query)
nested query selectors will not be removed:
const req = {}
req.query = { _id : { $ne: 1 } }
console.log(req.query)) // { _id: { '$ne': 1 } }
console.log(sanitize(req.query)) // { _id: { '$ne': 1 } }
Using deepSanitize(req.query)
sanitized objects (including nested) are mutated:
console.log(deepSanitize(req.query)) // { _id: {} }
console.log(req.query) // { _id: {} }
Eliminate object mutation with {...req.query}
:
console.log(deepSanitize({...req.query})) // { _id: {} }
console.log(req.query) // { _id: { '$ne': 1 } }