Use parameterized queries everywhere and avoid building SQL with string formatting or quoted placeholders. Django’s ORM is safer because it separates the query from its parameters, and the database driver escapes values correctly. When ORM is not enough, pass parameters through raw methods or cursor execute calls so user input is treated as data, not executable SQL.
Why parameterization matters even when you drop below Django’s ORM
Django’s ORM is the safest default because it keeps SQL structure separate from data values, but raw SQL can still be safe if you preserve that boundary. The practical rule is simple: write the query text once, then bind values through parameters so the driver escapes them as data rather than interpreting them as SQL. That applies to custom reporting, vendor-specific functions, and edge cases where the ORM cannot express the query cleanly.
The failure mode is usually not “raw SQL” itself, it is mixing user input into the SQL string before execution. String formatting, f-strings, concatenation, and manually quoted placeholders all collapse the query and the data into one executable string. Once that happens, even a small input that changes quotes, operators, or clauses can alter the intended statement. The safer pattern is to let the database adapter handle substitution every time, including for raw queries that still need to remain readable and maintainable.
When teams need a reference point for safe application query construction, the OWASP Top 10 remains the clearest baseline for sql injection risk, and Django teams should treat raw query code as part of that same control boundary.
What breaks first in Django code reviews
The most common review finding is a query that looks harmless because the input is “quoted,” yet still builds SQL text from untrusted values. Quoting is not a defense if the application is assembling executable SQL on its own. Another frequent issue is using raw queries for convenience and then slowly extending them with inline filters, sort clauses, or identifiers that were never validated as data.
There is also a subtle difference between values and SQL fragments. Parameters are appropriate for values such as names, IDs, dates, and search terms. They are not a substitute for structural elements like column names, sort direction, or table names, which cannot be safely parameterized in most drivers. In those cases, the safe pattern is to allow only a tightly controlled set of expected values and map them to known SQL fragments in code, rather than accepting free-form text.
For teams that want implementation detail beyond Django-specific patterns, the OWASP Cheat Sheet Series is a useful companion for input handling, while OWASP Top 10 anchors the broader injection threat model. If the query touches API-backed data flows as well, the OWASP API Security Top 10 is a good reminder that injection and broken access control often appear together.
Standards & Framework Alignment
This section maps relevant standards and security frameworks to the operational risks and controls described in this guidance.
OWASP Non-Human Identity Top 10 and OWASP Agentic AI Top 10 address the attack and risk surface, while CIS Controls v8 and NIST CSF 2.0 set the governance and control requirements practitioners need to meet.
| Framework | Control / Reference | Relevance |
|---|---|---|
| OWASP Non-Human Identity Top 10 | NHI-01 — Secrets and Credential Management | Raw SQL misuse often exposes secrets in code paths and data access layers. |
| Recommendation — Keep credentials and connection secrets out of query-building code. | ||
| CIS Controls v8 | CIS-16 — Application Software Security | SQL injection is a core application security weakness in custom query code. |
| CIS-6 — Access Control Management | Unsafe queries can bypass intended authorization boundaries on backend data. | |
| Recommendation — Validate custom SQL paths and enforce secure coding checks before release. Restrict database privileges so application accounts can only access required objects. | ||
| NIST CSF 2.0 | PR.AC-3 — Remote Access is Managed | Safe query execution depends on controlled, mediated access to backend data systems. |
| PR.DS-6 — Integrity is Protected | SQL injection threatens the integrity of application data and query results. | |
| Recommendation — Mediate application access to databases through controlled trust boundaries. Protect data integrity by preventing untrusted input from altering query logic. | ||
| OWASP Agentic AI Top 10 | A1 — Prompt Injection and Input Manipulation | The same input-separation principle applies when untrusted input can change execution meaning. |
| Recommendation — Treat all untrusted input as data and keep it isolated from executable instructions. | ||
Practitioner Guidance
What to prioritise: Review every raw query site for one thing first, whether user-controlled text reaches the SQL string before execution. If it does, treat that path as a security defect even if the current inputs appear internal or low risk.
What to verify: Confirm that each raw query uses the database driver’s parameter binding for all values, and that any unavoidable SQL fragments come from a fixed allowlist rather than from request data. Also verify that code reviews reject manually quoted placeholders, because they often look “parameterized” while still being unsafe.
Common mistake: Teams often secure the obvious WHERE clause but forget ORDER BY, LIMIT, field selection, and ad hoc reporting helpers. Those paths are frequent injection entry points because developers assume they are too minor to matter.
Practitioner takeaway: The right standard is not “raw SQL is allowed,” it is “raw SQL must preserve data-as-data separation everywhere the database accepts user influence.”
Related resources from NHI Mgmt Group
- How should teams prevent SQL injection in Laravel when they need to use raw queries?
- How should teams prevent SQL injection in Flask APIs that build queries dynamically?
- What is the difference between Django ORM queries and raw SQL when it comes to injection risk?
- How should Rails teams prevent SQL injection when building database queries from user input?
Deepen Your Knowledge
Reviewed and updated by the NHIMG editorial team on September 17, 2026.
NHI Mgmt Group — the #1 independent authority on Non-Human Identity, IAM, and Agentic AI security. nhimg.org