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-016 --project .About This Rule
Understanding the vulnerability and how it is detected
This rule detects injection vulnerabilities unique to serverless DynamoDB integrations in AWS Lambda functions, where untrusted event data flows into a DynamoDB FilterExpression string passed to table.scan() or table.query() calls.
DynamoDB is the most commonly used database for AWS Lambda functions due to its serverless scaling model, IAM-based access control, and native AWS integration. When Lambda functions use the low-level DynamoDB API with raw expression strings (rather than the high-level boto3 Attr() and Key() condition builder), event data can be injected into the FilterExpression string parameter.
Unlike SQL injection, DynamoDB FilterExpression injection does not enable arbitrary data access (DynamoDB does not support cross-table operations or nested expression execution). However, attackers can manipulate filter logic to bypass intended access controls, cause denial-of-service by injecting always-false conditions that return empty results, enumerate attribute names via error-based probing, or modify scan behavior to expose data that should be filtered out.
This vulnerability is specific to the serverless ecosystem: Lambda functions commonly skip the extra abstraction layer that would prevent it, and DynamoDB's expression language is less widely understood than SQL, making developers less likely to recognize injection patterns.
Security Implications
Potential attack scenarios if this vulnerability is exploited
Filter Logic Bypass via Expression Injection
An attacker who controls part of the FilterExpression string can inject expression syntax to bypass intended data access controls. For example, injecting OR attribute_exists(id) into a filter intended to restrict results to a specific user's records can cause the filter to return all items in the table rather than only the intended subset.
Access Control Bypass in Multi-Tenant Data
DynamoDB tables in Lambda applications often store multi-tenant data separated by a tenant_id attribute. FilterExpression injection can bypass tenant isolation by modifying the filter to include OR conditions that match items from other tenants, exposing cross-tenant data to attackers.
Denial of Service via Always-False Filters
Injecting always-false conditions (e.g., attribute_not_exists(id) when id always exists) causes table.scan() to consume all DynamoDB read capacity units while returning no results. For large tables with high read capacity costs, this can generate significant AWS charges and degrade application performance.
Attribute Name Enumeration via Error Probing
DynamoDB returns specific error messages for invalid expression attribute names. By injecting probe expressions and observing error responses, an attacker can enumerate the attribute names present in the DynamoDB table, revealing the data schema for use in more targeted attacks.
How to Fix
Recommended remediation steps
- 1Use boto3's Attr() and Key() condition expression builders instead of raw FilterExpression strings; the SDK handles value escaping and expression syntax automatically.
- 2Always use ExpressionAttributeValues and ExpressionAttributeNames for substitution when FilterExpression strings must be constructed programmatically.
- 3Validate event fields against strict allowlists before using them in any DynamoDB expression, particularly for attribute names that cannot be parameterized by the SDK.
- 4Apply DynamoDB IAM policies that restrict the Lambda's access to specific tables and operations (e.g., GetItem, Query only; no Scan on production tables).
- 5Prefer table.query() with KeyConditionExpression over table.scan() with FilterExpression; queries are more efficient and inherently scope to a partition key value.
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("*.scan") and calls("*.query") on DynamoDB Table objects when the tainted value reaches the FilterExpression string argument (tracked via .tracks(0)). The rule specifically flags raw string FilterExpression arguments that contain event data, not Attr()-based condition expressions. The analysis follows taint through f-string interpolation, string concatenation, 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 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.
Frequently Asked Questions
Common questions about Lambda DynamoDB FilterExpression Injection
New feature
Get these findings posted directly on your GitHub pull requests
The Lambda DynamoDB FilterExpression Injection rule runs in CI and posts inline review comments on the exact lines — no dashboard, no SARIF viewer.