Raw SQL Usage Audit via RawSQL Expression

MEDIUM

RawSQL() expression detected. Audit this usage to confirm parameterized queries are used for all user-controlled values.

Rule Information

Language
Python
Category
Django
Author
Shivasurya
Shivasurya
Last Updated
2026-03-22
Tags
pythondjangosql-injectionrawsqlauditormCWE-89OWASP-A03
CWE References

Interactive Playground

Experiment with the vulnerable code and security rule below. Edit the code to see how the rule detects different vulnerability patterns.

pathfinder scan --ruleset python/PYTHON-DJANGO-SEC-005 --project .
1
2
3
4
5
6
7
8
rule.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

About This Rule

Understanding the vulnerability and how it is detected

This audit rule flags all usages of the RawSQL() expression in Django applications regardless of whether tainted data is detected flowing into the SQL string. It is a visibility rule designed to surface all raw SQL expressions for manual security review.

Django's RawSQL() allows embedding raw SQL fragments in ORM querysets via annotate(), filter(), and order_by(). When used correctly with a static SQL string and all dynamic values passed via the params tuple, it is safe. However, these usages are frequently modified by developers who later add dynamic values without realizing they must also update the params argument.

This rule uses pattern matching on DjangoExpressions.method("RawSQL") rather than taint analysis, providing full coverage of all RawSQL() call sites in the codebase. This makes it suitable for security audits and compliance reviews where a complete inventory of raw SQL usage is required.

Security Implications

Potential attack scenarios if this vulnerability is exploited

1

Latent Injection Risk from Future Modifications

Even currently-safe RawSQL() calls with static SQL strings represent a latent risk. Developers who later modify these calls to include dynamic values may inadvertently embed them in the SQL string instead of the params tuple, introducing injection vulnerabilities that are not immediately obvious during code review.

2

Audit Coverage for Compliance

Security audits, penetration testing reports, and compliance frameworks often require a complete inventory of raw SQL usage. This rule provides that inventory for RawSQL() specifically, complementing taint-based rules that only flag confirmed injection flows.

3

Injection via Third-Party Code

RawSQL() usages in shared utility functions or mixins may be called from multiple views, some of which may pass user-controlled data as the SQL string. Auditing all call sites identifies these shared functions that need careful review of all their callers.

4

Database-Specific SQL in Annotations

RawSQL() is often used for database-specific functions not available in Django's ORM. These usages may be less scrutinized during code review because they are seen as necessary technical debt, making them a common location for overlooked injection vulnerabilities.

How to Fix

Recommended remediation steps

  • 1Treat every RawSQL() call site as requiring security review to confirm the SQL string is a static literal.
  • 2Migrate RawSQL() usages to equivalent Django ORM expressions (F(), Value(), Case(), database functions) wherever possible to eliminate the audit surface.
  • 3Document the reason for each RawSQL() call in a code comment explaining why ORM alternatives are insufficient.
  • 4Enforce code review policy requiring security sign-off on new RawSQL() additions.
  • 5Use PYTHON-DJANGO-SEC-004 (taint-based rule) in CI to catch actual injection flows, and this audit rule for periodic compliance reviews.

Detection Scope

How Code Pathfinder analyzes your code for this vulnerability

This rule uses QueryType pattern matching rather than taint analysis. It matches all calls to DjangoExpressions.method("RawSQL") regardless of whether user-controlled data flows into the arguments. The .where() clause constrains matches to Python files in Django projects. This rule is intended as an audit/inventory tool and will produce findings for all RawSQL() usages including correctly-parameterized ones. Use it for security audits and compliance reviews. For CI-integrated injection detection, use PYTHON-DJANGO-SEC-004 instead to avoid noise from safe usages.

Compliance & Standards

Industry frameworks and regulations that require detection of this vulnerability

CWE Top 25
CWE-89 ranked #3 in 2023 Most Dangerous Software Weaknesses
OWASP Top 10
A03:2021 - Injection
PCI DSS v4.0
Requirement 6.2.4 and 6.3.2 - inventory of custom code and protection against injection
NIST SP 800-53
SI-10: Information Input Validation; RA-5: Vulnerability Monitoring and Scanning
ISO 27001
A.14.2.8 - System security testing

References

External resources and documentation

Similar Rules

Explore related security rules for Python

Frequently Asked Questions

Common questions about Raw SQL Usage Audit via RawSQL Expression

This is an audit rule, not a taint-based injection rule. It flags all RawSQL() usages regardless of whether they are safe. This is intentional: it creates an inventory of all raw SQL usage for security review. Use PYTHON-DJANGO-SEC-004 for taint-based injection detection in CI. This rule is better suited for periodic security audits and compliance reviews.
Add a comment documenting why the RawSQL() usage is safe and configure a suppression annotation. Alternatively, maintain an allowlist of approved RawSQL() calls in your security documentation. The goal of this audit rule is visibility, not zero findings -- all findings should be reviewed and disposition documented.
SEC-004 uses taint analysis to detect confirmed injection flows from request parameters to RawSQL() SQL strings. SEC-005 uses pattern matching to flag all RawSQL() usages regardless of data flow. SEC-004 has fewer false positives and is appropriate for CI gates. SEC-005 has higher coverage and is appropriate for security audits where completeness matters more than precision.
Yes. Configure two separate rule sets in your CI pipeline: one for PR checks that includes only taint-based rules like SEC-004, and one for scheduled security scans or release gates that includes audit rules like SEC-005. This gives you fast PR feedback without noise while maintaining complete audit coverage.
In practice, most RawSQL() usages that are flagged by this audit rule are safe because they use the params argument correctly. The value of this rule is in catching the minority that do not, and in ensuring all usages are documented and reviewed. Teams maintaining large Django codebases often discover 5-15% of RawSQL() calls lack proper parameterization when running this audit.

New feature

Get these findings posted directly on your GitHub pull requests

The Raw SQL Usage Audit via RawSQL Expression rule runs in CI and posts inline review comments on the exact lines — no dashboard, no SARIF viewer.

See how it works