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-LAMBDA-SEC-013 --project .About This Rule
Understanding the vulnerability and how it is detected
This rule detects SQL injection vulnerabilities in AWS Lambda functions where untrusted event data flows into PyMySQL cursor.execute() calls without proper parameterization, enabling SQL injection against RDS MySQL, Aurora MySQL, or any MySQL-compatible backend accessed via the pure-Python PyMySQL driver.
PyMySQL is the most commonly used MySQL driver in AWS Lambda functions because it is a pure-Python library that requires no compiled extensions, making it easy to package as a Lambda deployment artifact or Lambda Layer. Lambda functions triggered by API Gateway, SQS, SNS, S3, and other sources receive attacker-controllable event data (event.get("body"), event.get("queryStringParameters"), event["Records"]).
When this event data is concatenated or f-stringed into the SQL string before being passed to cursor.execute(), the PyMySQL driver receives a pre-built SQL string with the injected payload already embedded. PyMySQL's own escaping (connection.escape()) is only applied when values are passed through the parameters mechanism. Embedding values in the SQL string bypasses all driver-level protection.
Security Implications
Potential attack scenarios if this vulnerability is exploited
Full Database Exfiltration
An attacker who controls any SQL fragment can use UNION SELECT to read from any table accessible to the Lambda's MySQL user. PyMySQL provides no protection when event data is embedded in the SQL string, making all accessible tables vulnerable to exfiltration in a single injected query.
Authentication Bypass in Serverless Authentication Flows
Lambda functions often implement stateless authentication by querying user records via PyMySQL. Injecting ' OR '1'='1'-- into username or password fields causes the query to return all rows, bypassing authentication for any user account in the table.
Data Modification via Stacked Queries
PyMySQL can execute multiple statements when execute_multiple is enabled. An attacker can inject additional INSERT, UPDATE, or DELETE statements after the original query to modify application data, create backdoor accounts, or corrupt records. Even without stacked queries, subquery injection can achieve data modification in some contexts.
Lambda Warm Instance Exploitation
PyMySQL connections cached across warm Lambda invocations mean that a successful injection in one invocation can observe the results of data modifications made in subsequent invocations using the same connection, enabling multi-step attacks across what appear to be independent Lambda executions.
How to Fix
Recommended remediation steps
- 1Always pass Lambda event data as the second argument to cursor.execute() as a tuple, never by concatenating it into the SQL string.
- 2Use PyMySQL's DictCursor for named column access rather than index-based access, which reduces the risk of using wrong column values in query construction.
- 3Grant the Lambda's MySQL user the minimum necessary privileges (SELECT on specific tables) and avoid GRANT ALL or SUPER privileges.
- 4Cache the PyMySQL connection at module level and use connection.ping(reconnect=True) to reuse it across warm invocations without re-authenticating.
- 5Enable RDS MySQL general query logging selectively or use Performance Schema to audit queries and detect injection patterns.
Detection Scope
How Code Pathfinder analyzes your code for this vulnerability
This rule performs inter-procedural taint analysis with global scope. Sources are Lambda event dictionary access calls: calls("event.get"), calls("event.__getitem__"), including event.get("body"), event.get("queryStringParameters"), event.get("pathParameters"), and event["Records"]. The sink is calls("*.execute") matching PyMySQL cursor objects with the tainted SQL string tracked via .tracks(0) (the query string argument). Sanitizers include explicit int() or float() type conversion and connection.escape() when correctly applied. The analysis follows taint through string concatenation, f-string interpolation, variable assignments, and function boundaries.
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
Lambda SQL Injection via psycopg2 cursor.execute()
Lambda event data flows to psycopg2 cursor.execute() without parameterization, enabling SQL injection against RDS PostgreSQL or Aurora PostgreSQL backends.
Lambda SQL Injection via pymssql cursor.execute()
Lambda event data flows to pymssql cursor.execute() without parameterization, enabling SQL injection against RDS SQL Server backends.
Lambda SQL Injection via SQLAlchemy execute()
Lambda event data flows to SQLAlchemy session.execute() or connection.execute() without bound parameters, enabling SQL injection against any RDS backend.
Frequently Asked Questions
Common questions about Lambda SQL Injection via PyMySQL cursor.execute()
New feature
Get these findings posted directly on your GitHub pull requests
The Lambda SQL Injection via PyMySQL cursor.execute() rule runs in CI and posts inline review comments on the exact lines — no dashboard, no SARIF viewer.