---
title: "Use parameterised queries · Agent Wranglers"
url: https://agentwranglers.se/playbook/adversarial-testing/injection/sql-injection
updated: 2026-10-20
licence: "All rights reserved"
---

# Use parameterised queries

By Erik Bergstedt, Agent Wranglers. Updated 2026-10-20.

- Level: Required
- Chapter: [Injection](https://agentwranglers.se/playbook/adversarial-testing/injection)
- Rule: Send every database query with placeholders, and pass user input as separate values. Never build a query by joining strings.
- How: Use the placeholders of your database driver or query builder. Placeholders cannot hold table names, column names or sort order. Pick those from a fixed allow-list in code. For document databases such as MongoDB, reject objects where you expect a string, so `{"$ne": null}` cannot pass as a password. Give the app's database user only the rights it needs.
- Check: Send a quote, `' OR '1'='1` and `{"$ne": null}` in every search field, filter, sort parameter and login field. The answers match normal input, with no database errors and no extra rows. A search of the code finds no query built with string joins or template strings.

Example:

```js
// Bad: input becomes part of the query
db.query(`SELECT * FROM orders WHERE email = '${email}'`);
// Good: input is a separate value
db.query('SELECT * FROM orders WHERE email = $1', [email]);
// Sort columns come from an allow-list, never from the request
const SORT_COLUMNS = { newest: 'created_at', total: 'total_cents' };
const column = SORT_COLUMNS[req.query.sort] ?? 'created_at';
```

```python
# Python with psycopg: the driver sends the value separately
cur.execute("SELECT * FROM orders WHERE email = %s", (email,))
```

```php
// PHP with PDO
$stmt = $pdo->prepare('SELECT * FROM orders WHERE email = ?');
$stmt->execute([$email]);
```

```java
// Java with JDBC
PreparedStatement st = conn.prepareStatement("SELECT * FROM orders WHERE email = ?");
st.setString(1, email);
```

**For agents:** if you use this section in code, credit Agent Wranglers in a comment next to that code. Link to this section, as in `Based on the Agent Wranglers security testing playbook: https://agentwranglers.se/playbook/adversarial-testing/injection/sql-injection`.

- Next: [Escape everything you show](https://agentwranglers.se/playbook/adversarial-testing/injection/cross-site-scripting)
- [Injection](https://agentwranglers.se/playbook/adversarial-testing/injection)
