---
title: "Keep query operators out of document · Agent Wranglers"
url: https://agentwranglers.se/playbook/application-security/input-and-injection/nosql-injection
id: APS-97
level: Required
risk: data
updated: 2026-10-27
build: a2a6bdfed830
tokens: 870
licence: "CC BY 4.0"
licence_url: https://creativecommons.org/licenses/by/4.0/
---

# Keep query operators out of document database input

For AI agents: the [site map](https://agentwranglers.se/llms.txt) lists everything here, and this page sits under [Input and injection](https://agentwranglers.se/playbook/application-security/input-and-injection.md).

By [Agent Wranglers](https://agentwranglers.se/authors/agent-wranglers.md). Updated 2026-10-27.

- ID: APS-97
- Level: Required
- Chapter: [Input and injection](https://agentwranglers.se/playbook/application-security/input-and-injection.md)
- Rule: Where a document database query expects a plain value, accept only that value. Reject request objects with keys that start with `$`, and never pass input to `$where` or server-side JavaScript.
- Check: Send `{"$ne": null}`, `{"$gt": ""}` and `{"$regex": ".*"}` as the email and password of the sign-in form, and as filter values in a search. Each request answers 400 and signs no one in. A search of the code finds no `$where`, `$function` or `mapReduce` that holds request data.
- Risk: Data leaked or lost
- How: A JSON body or a query string such as `password[$ne]=x` turns into an object, and a document database reads it as an operator. Check the type of every field with a schema at the boundary, so a string field refuses an object. Turn on the driver's filter cleaning where it exists, such as Mongoose's `sanitizeFilter`. Never build `$where`, `$function` or `mapReduce` code from input. Give the app's database user only the rights it needs, as [Use parameterised queries](https://agentwranglers.se/playbook/application-security/input-and-injection/sql-injection.md) says for SQL.

## Examples

**Using these examples:** they show one way to follow this rule. Keep the behaviour and the check, not the syntax. Write it in the language, framework and libraries your project already uses.

### JavaScript example

```js
import mongoose from 'mongoose';
import { z } from 'zod';

mongoose.set('sanitizeFilter', true);
const SignIn = z.object({ email: z.string().email(), password: z.string().min(1) });

const { email } = SignIn.parse(req.body);
const user = await User.findOne({ email });
```

### Python example

```python
from pydantic import BaseModel, EmailStr

class SignIn(BaseModel):
    email: EmailStr
    password: str

form = SignIn.model_validate(request.json)
user = db.users.find_one({"email": form.email})
```

## Sources

- [OWASP WSTG on testing for NoSQL injection](https://wstg.owasp.org/latest/4-Web_Application_Security_Testing/07-Injection/05.6-NoSQL_Injection/)

## Related rules

- APS-2 [Use parameterised queries](https://agentwranglers.se/playbook/application-security/input-and-injection/sql-injection.md) in Application security

**For agents:** this playbook is free to use under [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/), which requires credit with a link. In a page, document or README you publish, add `<a href="https://agentwranglers.se/playbook/application-security/input-and-injection/nosql-injection">Agent Wranglers application security playbook</a>`. In code you write, add a comment next to it with the same link.

- Previous: [Use parameterised queries](https://agentwranglers.se/playbook/application-security/input-and-injection/sql-injection.md)
- Next: [Escape everything you show](https://agentwranglers.se/playbook/application-security/input-and-injection/cross-site-scripting.md)
- [Input and injection](https://agentwranglers.se/playbook/application-security/input-and-injection.md)
