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-FLASK-SEC-003 --project .About This Rule
Understanding the vulnerability and how it is detected
This rule catches a specific pattern: user input from Flask request parameters (request.args, request.form, request.get_json) gets concatenated or f-stringed into a SQL query, then passed to cursor.execute(). The fix is straightforward -- use parameterized queries instead of string building.
What makes this rule different from a simple grep for "execute" is that it actually traces data flow. If the user input arrives in app.py, gets assigned to a variable, passed through a function call into db.py, and ends up in cursor.execute() three hops later -- Code Pathfinder follows that chain and flags it. It also knows the difference between cursor.execute(query_string) (dangerous, argument position 0) and cursor.execute(sql, (params,)) (safe, the tuple at position 1 is the parameterization mechanism). That distinction alone eliminates a class of false positives that trips up most static analysis tools.
Security Implications
Potential attack scenarios if this vulnerability is exploited
Data Exfiltration
An attacker can read your entire database. UNION-based injection pulls data from other tables. Blind injection extracts it one bit at a time. Either way, one vulnerable endpoint is enough to leak every row in every table.
Authentication Bypass
The classic ' OR 1=1 -- in a login form. The query returns all users, the app logs in as the first one (usually admin). No brute force needed, no credentials required.
Data Manipulation
Injected INSERT, UPDATE, or DELETE statements can modify records, create backdoor accounts, or corrupt data. In financial applications, this means altered transactions.
Remote Code Execution
Some databases let you run OS commands: PostgreSQL has COPY, MySQL has INTO OUTFILE, MSSQL has xp_cmdshell. SQL injection on these systems can escalate to full server compromise.
How to Fix
Recommended remediation steps
- 1Use parameterized queries -- cursor.execute("SELECT * FROM users WHERE name = ?", (username,)) -- not string concatenation
- 2Switch to an ORM like SQLAlchemy if you're writing raw SQL frequently
- 3Validate and type-check input before it reaches the database layer
- 4Run database accounts with least privilege so a compromised query can't DROP tables
- 5Log SQL queries in production to catch injection attempts early
Detection Scope
How Code Pathfinder analyzes your code for this vulnerability
This rule traces data across files (scope=global). It starts from Flask request methods -- request.args.get, request.form.get, request.values.get, request.get_json, request.cookies.get, request.headers.get -- and follows variables through assignments and function calls until they reach cursor.execute() or cursor.executemany(). The .tracks(0) setting means only the SQL string argument (position 0) triggers a finding. The parameter tuple at position 1 is ignored. Flows through escape() or escape_string() are treated as sanitized and excluded.
Compliance & Standards
Industry frameworks and regulations that require detection of this vulnerability
References
External resources and documentation
Similar Rules
Explore related security rules for Python
Django SQL Injection via cursor.execute()
User input flows to cursor.execute() without parameterization, enabling SQL injection attacks.
Django SQL Injection via QuerySet.raw()
User input flows to QuerySet.raw() without parameterization, enabling SQL injection through Django's ORM raw query interface.
psycopg2 SQL Injection via String Formatting
SQL query built with string formatting passed to psycopg2 cursor.execute() enables SQL injection. Use parameterized queries with %s placeholders.
Frequently Asked Questions
Common questions about Flask SQL Injection via Tainted String
New feature
Get these findings posted directly on your GitHub pull requests
The Flask SQL Injection via Tainted String rule runs in CI and posts inline review comments on the exact lines — no dashboard, no SARIF viewer.