pi-lens
Version:
Real-time code feedback for pi — LSP, linters, formatters, type-checking, structural analysis & booboo
58 lines (46 loc) • 1.42 kB
YAML
# Python Security
# Detects dynamic SQL passed into execute-like APIs.
id: python-sql-injection
name: SQL Injection Risk
severity: error
category: security
defect_class: injection
inline_tier: blocking
language: python
message: "Potential SQL injection sink — use parameterized queries"
description: |
Dynamic SQL strings passed to execute-style APIs can enable SQL injection.
Catches:
- cursor.execute("SELECT " + var) — string concatenation (always unsafe)
- cursor.execute(dynamic_sql) — variable with NO params arg (could be unsafe)
Suppressed:
- cursor.execute(query, params) — parameterized query (safe)
- session.execute(select(...)) — SQLAlchemy ORM (safe by construction)
- cursor.execute(f"...") — f-string with literal-only interpolation (rare false positive)
✅ FIX: use placeholders and parameter binding instead of string composition.
query: |
(call
function: (attribute
object: (_) @OBJ
attribute: (identifier) @FN)
arguments: (argument_list
[(binary_operator) (identifier) (call)] @SQL
(_)*) @ARGS)
metavars:
- OBJ
- FN
- SQL
- ARGS
post_filter: py_sql_injection_sink
has_fix: false
tags:
- python
- security
- sql-injection
- cwe-89
- owasp-a03
examples:
bad: |
cursor.execute("SELECT * FROM users WHERE id = " + user_id)
good: |
cursor.execute("SELECT * FROM users WHERE id = %s", (user_id,))