Web App Security & OWASP Top 10
How to prevent SQL Injection (SQLi) vulnerabilities completely in modern web frameworks?
Prevent SQLi by exclusively using prepared statements/ORM bindings, strict validation, and CSP; never concatenate user input into SQL.
A
Aravind Patel
👑 Tier 3 Elite
Aug 9, 2026 · 2 min read
Use parameterized queries (prepared statements) exclusively, and let the framework’s ORM handle all data binding. Combine this with built‑in request validation, a strict content‑type policy, and CSP to eliminate injection vectors.
1. **Choose a modern framework with built‑in ORM** – Django (Python), Spring Data JPA (Java), Laravel Eloquent (PHP), or ASP.NET Core Entity Framework.
2. **Never concatenate raw input into SQL** – always use `?`, `$1`, `:name` placeholders.
3. **Enable automatic query sanitisation** – e.g., `django.db.models` automatically escapes values; in Spring use `@Query` with `?1` parameters.
4. **Validate and type‑cast all request data** – use schema validators like `pydantic`, `javax.validation`, or Laravel Form Requests; reject anything that fails.
5. **Enforce `Content‑Type: application/json` (or form‑encoded) and reject unknown media types** – in Express: `app.use(express.json({ strict: true }))`.
6. **Apply a CSP that disallows inline scripts** – `Content‑Security-Policy: script-src 'self'`.
7. **Run a static analysis tool on every PR** – `bandit` for Python, `SpotBugs` with FindSecBugs for Java, `phpstan` with security rules.
**Quick comparison**
| Approach | Parameter handling | Auto‑escaping | Typical API |
|----------|-------------------|--------------|------------|
| Raw SQL | Manual (`%s`) | No | `cursor.execute(sql, params)` |
| ORM | Implicit (`.filter()`) | Yes | `User.objects.filter(id=uid)` |
| Query Builder | Chain (`.where()`) | Yes | `knex('users').where('id', uid)` |
**Example (Python psycopg2)**
```python
import psycopg2
conn = psycopg2.connect(dsn)
cur = conn.cursor()
cur.execute("SELECT * FROM users WHERE email = %s", (email,))
```
**Example (Java Spring JDBC)**
```java
String sql = "SELECT * FROM users WHERE email = ?";
List users = jdbcTemplate.query(sql, new Object[]{email}, new UserRowMapper());
```
**Gotcha:** Dynamic identifiers (table or column names) cannot be parameterised; whitelist them against a static list before constructing the query, otherwise an attacker can still inject via those paths.
Read the evidence
Sources used in this thread
Open the original material, compare the claims, and form your own view.