HIGH nosql injectionfastapidynamodb

Nosql Injection in Fastapi with Dynamodb

Nosql Injection in Fastapi with Dynamodb — how this specific combination creates or exposes the vulnerability

NoSQL injection in a FastAPI application that uses Amazon DynamoDB typically arises when user-controlled input is directly interpolated into DynamoDB expressions rather than being passed as expression attribute values. DynamoDB’s PartiQL and ConditionExpression syntax support placeholders denoted by a colon (:) for expression attribute values. If a developer builds expressions by string concatenation and embeds raw user input, an attacker can change the structure of the expression and affect unintended attributes or conditions.

Consider a login endpoint that retrieves a user by username. A vulnerable implementation might concatenate the username into the key condition or filter expression:

username = user_input # attacker can supply: ' OR begins_with(#status, 'admin')
response = table.query(
    KeyConditionExpression=Key('username').eq(username)
)

Because the username is placed directly into the expression, an attacker can break out of the intended equality check. Even when using the AWS SDK, expressions that include user input in attribute names (e.g., for sorting or filtering on dynamic fields) are risky if not parameterized. Dangerous patterns also appear when building UpdateExpression or DeleteExpression with string formatting, where an attacker-supplied attribute name can target system attributes like aws:dynamodb:LeadingKeys or overwrite critical fields.

FastAPI does not inherently protect against this: if you manually construct DynamoDB expressions from request bodies, query parameters, or path segments, the responsibility is on the developer to treat all external data as untrusted. Common vulnerable sources include path parameters, JSON payload fields used for filtering, and header values used to select table attributes. Because DynamoDB does not have a SQL-like parser that separates code from data in the same way, failing to use expression attribute names and expression attribute values correctly leads to injection. Attack outcomes can include bypassing authentication, reading other users’ records (IDOR), or causing inefficient queries that affect performance.

In a black-box scan, middleBrick tests such scenarios by submitting strings that attempt to change query semantics, like supplying values that should never match a partition key or injecting filter fragments. These tests validate whether user input is safely handled as values rather than being interpreted as expression syntax. Because DynamoDB’s SDKs serialize requests to JSON, injection usually occurs at the application layer before the SDK call, making server-side validation and strict use of parameterization essential.

Dynamodb-Specific Remediation in Fastapi — concrete code fixes

Remediation centers on two DynamoDB-specific practices: always use expression attribute names for identifiers (including attribute names) and always use expression attribute values for data. Never concatenate user input into expression strings.

1) Query with safe key condition and expression attribute values:

from fastapi import FastAPI, Query
import boto3
from boto3.dynamodb.conditions import Key

app = FastAPI()
dynamodb = boto3.resource('dynamodb', region_name='us-east-1')
table = dynamodb.Table('users')

@app.get('/users/{username}')
def get_user(username: str = Query(...)):
    response = table.get_item(
        Key={'username': username}
    )
    return response.get('Item', {})

@app.get('/users/')
def list_users(status: str = Query('active')):
    response = table.query(
        KeyConditionExpression=Key('status').eq(status),
        ExpressionAttributeNames={'#username': 'username'},
        ExpressionAttributeValues={':val': status}
    )
    return response.get('Items', [])

In the list_users example, the filter value status is provided as an expression attribute value (:val), and if you needed to reference a reserved word as an attribute name, you would use ExpressionAttributeNames (e.g., #username). This ensures that user input cannot change the structure of the expression.

2) Update with named placeholders for both attribute names and values:

def update_user_status(username: str, new_status: str):
    table.update_item(
        Key={'username': username},
        UpdateExpression='SET #st = :new',
        ConditionExpression='username = :user',
        ExpressionAttributeNames={'#st': 'status'},
        ExpressionAttributeValues={':new': new_status, ':user': username}
    )

Here, #st is an expression attribute name and :new and :user are expression attribute values. This pattern prevents injection via attribute names or values. For scans and queries that accept user-supplied filter criteria, enforce strict allowlists for attribute names and validate data types before using ExpressionAttributeNames.

Additionally, enable DynamoDB Streams and use middleware or consumer logic to detect unexpected patterns, but remember that detection complements secure coding; it does not replace correct expression construction. middleBrick can be used in your workflow to validate that endpoints using DynamoDB do not exhibit injection-prone behaviors by submitting unauthenticated probes that attempt to modify query semantics, helping you catch regressions before they reach production.

For teams managing many APIs, the middleBrick CLI allows you to scan from terminal with middlebrick scan <url>, and the GitHub Action can add API security checks to your CI/CD pipeline, failing builds if risk scores drop below your chosen threshold. This ensures DynamoDB-related issues are caught early in development rather than in production.

Frequently Asked Questions

Can using ExpressionAttributeNames alone prevent NoSQL injection with DynamoDB in FastAPI?
No. ExpressionAttributeNames only protect attribute names from injection; you must also use ExpressionAttributeValues for all user-supplied data. Both practices together, along with avoiding string concatenation in expressions, are required to prevent NoSQL injection.
Does DynamoDB’s SDK automatically protect against injection if I use the high-level API?
No. The SDK serializes your expressions and values, but if you build expressions by embedding user input, the SDK will send the injected expression to DynamoDB. Safe construction using expression attribute names and values must be done in application code.