To protect against SQL injection, clients can use MongoDB's language APIs. This way, all the input is simple value - commands cannot be injected. A Java example:
collection.find(Filters.eq("key", "input value"))
The drawback is that you cannot easily test your filter. You cannot copy it to Mongo's shell and test it. Especially problematic with bigger, more complex filters/queries.
BUT!!! there's also an API to not use the filter's API - enabling to parse any json filter. Java example below:
collection.find(BasicDBObject.parse("{key: "input value"}"));
This is nice because you can copy the filter directly to the MongoDB shell to test it out.
BUT!!! (last but, I promise) this is prone to NoSql injection. Java example, where the input value is {$gt: ""}.
collection.find(BasicDBObject.parse("{key: {$gt: ""}}"));
In this last example, everything is returned, even though we meant only for the specific records to return.
See here a more thorough explanation on SQL injection when using the filters directly.
One last thing. I think there's a way to use both raw filters and still protect against SQL injection. For example, in Java, we can use Jongo's parameterized queries.
body-parserwith the nodejsexpresslib, for example). If you're parsing post parameters as JSON (which is fairly common) and then passing those parameters (or properties of those parameters) directly into a mongo query, then an attacker can insert a js object where you expected a string/number (e.g. they could pass{$gt:-1}and view all the documents in your collection)