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-011 --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 psycopg2 cursor.execute() calls without proper parameterization, enabling SQL injection against RDS PostgreSQL, Aurora PostgreSQL, or any PostgreSQL-compatible backend.
Lambda functions frequently connect to RDS PostgreSQL or Aurora PostgreSQL using psycopg2, the standard Python PostgreSQL adapter. Event data from API Gateway, SQS, SNS, S3, and other triggers (event.get("body"), event.get("queryStringParameters"), event["Records"]) is attacker-controllable and must not be embedded in SQL strings.
When event data is concatenated or f-stringed into the SQL query string before being passed as the first argument to cursor.execute(), an attacker can inject arbitrary SQL. PostgreSQL is particularly powerful as an injection target: attackers can use COPY TO/FROM PROGRAM to execute OS commands (on unmanaged PostgreSQL; RDS restricts this but not all extensions), pg_read_file() to read server files, and UNION SELECT to exfiltrate arbitrary tables. Lambda functions connecting to PostgreSQL typically lack the ORM layer that encourages parameterization, making raw psycopg2 calls a common source of injection vulnerabilities.
Security Implications
Potential attack scenarios if this vulnerability is exploited
Full Database Exfiltration via UNION SELECT
An attacker who controls any SQL fragment can use UNION SELECT to read from any table accessible to the Lambda's database user, including user credentials, session tokens, PII, and financial records stored in the RDS PostgreSQL database.
PostgreSQL Extension Abuse
PostgreSQL supports extensions that can be leveraged via SQL injection. dblink and postgres_fdw can be used to connect to other database servers. Large object functions (lo_import, lo_export) can read and write server files on unmanaged PostgreSQL. Even on RDS where these are restricted, schema enumeration and data exfiltration remain fully possible.
Authentication and Authorization Bypass
Lambda functions that validate user credentials or check authorization via SQL queries are vulnerable to ' OR '1'='1 style bypasses that cause the query to return all rows. This can grant attackers administrative access or allow them to act as any user in the system.
Second-Order Injection via Stored Data
Injection payloads stored in the database by one Lambda function can be triggered by a different Lambda function that reads the data and passes it to another cursor.execute() without re-parameterizing. This cross-function second-order injection is harder to detect and requires end-to-end taint tracking.
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 psycopg2's %s placeholders for all parameterized queries; never use Python string formatting (%, .format(), f-strings) to build SQL strings.
- 3Grant the Lambda's PostgreSQL user the minimum necessary privileges (CONNECT, SELECT on specific tables) and avoid SUPERUSER or CREATEROLE grants.
- 4Enable RDS PostgreSQL's pg_stat_activity logging and set log_min_duration_statement to detect slow or unusual queries that may indicate injection.
- 5Use RDS Proxy for connection pooling to prevent connection exhaustion from Lambda's per-invocation connection model.
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 psycopg2 cursor objects with the tainted SQL string tracked via .tracks(0) (the query string argument). Sanitizers include explicit int() or float() type conversion. 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 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 PyMySQL cursor.execute()
Lambda event data flows to PyMySQL cursor.execute() without parameterization, enabling SQL injection against RDS MySQL or Aurora MySQL backends via the pure-Python driver.
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 psycopg2 cursor.execute()
New feature
Get these findings posted directly on your GitHub pull requests
The Lambda SQL Injection via psycopg2 cursor.execute() rule runs in CI and posts inline review comments on the exact lines — no dashboard, no SARIF viewer.