HIGH command injectionfastapidynamodb

Command Injection in Fastapi with Dynamodb

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

Command Injection occurs when untrusted input is passed to a system command without proper validation or escaping. In a Fastapi application that interacts with DynamoDB, the risk emerges not from DynamoDB itself—DynamoDB is a NoSQL database and does not execute shell commands—but from how application code constructs and invokes operating system commands using data that may originate from or be influenced by DynamoDB records.

For example, a Fastapi endpoint might query DynamoDB for a file name or a system identifier, then pass that value to a shell utility such as subprocess.run or os.system without sanitization. If an attacker can control the data stored in or retrieved from DynamoDB—perhaps by writing a malicious value through another API path or exploiting insufficient access controls—they can inject shell metacharacters like ;, &, or | that alter command behavior. This chain—DynamoDB as a data source, Fastapi as the orchestrator, and a shell command as the execution target—creates a viable injection path.

Consider a scenario where an endpoint retrieves an object key from DynamoDB and uses it to generate a report via a command-line tool. A vulnerable implementation might look like this:

import subprocess
from fastapi import FastAPI
import boto3

app = FastAPI()
dynamodb = boto3.resource('dynamodb')
table = dynamodb.Table('Items')

@app.get('/generate/{item_id}')
def generate_report(item_id: str):
    response = table.get_item(Key={'id': item_id})
    item = response.get('Item', {})
    filename = item.get('filename', 'report')
    # Unsafe: user-influenced data from DynamoDB used in shell command
    result = subprocess.run(['generate-report', '--name', filename], capture_output=True, text=True)
    return {'output': result.stdout}

If the filename attribute in DynamoDB contains something like report; rm -rf /, the command executed becomes generate-report --name report; rm -rf /, causing unintended system operations. Even if DynamoDB access is restricted, other vectors—such as log injection or secondary data stores—might feed attacker-controlled values into command construction.

The LLM/AI Security checks included in middleBrick specifically test for scenarios where system prompts or outputs could indirectly influence command construction, and they help identify risky patterns such as unchecked concatenation of external data into shell invocations. While middleBrick does not fix these issues, its findings provide prioritized guidance and remediation steps to help developers address such risks.

Dynamodb-Specific Remediation in Fastapi — concrete code fixes

Defending against Command Injection when Fastapi interacts with DynamoDB requires strict input validation, avoiding shell metacharacters in dynamic arguments, and using safe execution patterns. Below are concrete, executable code examples that demonstrate secure practices.

1. Avoid Shell=True and Use Argument Lists

Never use shell=True, and always pass commands as a list of arguments. This prevents the shell from interpreting metacharacters. Validate and sanitize any string that originates from DynamoDB before use.

import subprocess
from fastapi import FastAPI, HTTPException
import re
import boto3

app = FastAPI()
dynamodb = boto3.resource('dynamodb')
table = dynamodb.Table('Items')

def is_safe_filename(value: str) -> bool:
    # Allow only alphanumeric, underscore, hyphen, and limited safe extensions
    return re.match(r'^[A-Za-z0-9_.\-]+$', value) is not None

@app.get('/generate/{item_id}')
def generate_report(item_id: str):
    response = table.get_item(Key={'id': item_id})
    item = response.get('Item', {})
    filename = item.get('filename', 'report')
    if not is_safe_filename(filename):
        raise HTTPException(status_code=400, detail='Invalid filename')
    # Safe: argument list, no shell interpretation
    result = subprocess.run(['generate-report', '--name', filename], capture_output=True, text=True)
    return {'output': result.stdout}

2. Use AWS SDK Operations Instead of Shell Commands

Whenever possible, perform operations directly via the AWS SDK rather than invoking external commands. This eliminates shell injection risk entirely and is more efficient.

from fastapi import FastAPI, HTTPException
import boto3
from botocore.exceptions import ClientError

app = FastAPI()
dynamodb = boto3.resource('dynamodb')
table = dynamodb.Table('Items')

@app.get('/items/{item_id}')
def get_item_details(item_id: str):
    try:
        response = table.get_item(Key={'id': item_id})
        item = response.get('Item')
        if not item:
            raise HTTPException(status_code=404, detail='Item not found')
        # Direct SDK usage avoids shell entirely
        return item
    except ClientError as e:
        raise HTTPException(status_code=500, detail=str(e))

3. Input Validation and Allowlisting

Apply strict allowlists for any data used in command-like contexts. For identifiers, prefer UUIDs or numeric IDs that match a predictable pattern, and reject any input containing shell metacharacters.

import re

def validate_identifier(value: str) -> bool:
    # Strict alphanumeric and hyphen pattern
    return re.fullmatch(r'[A-Za-z0-9\-]+', value) is not None

Use this validator before constructing any external call. Combine these practices with middleBrick’s scanning workflow—using the CLI to run middlebrick scan <url> or integrating the GitHub Action to fail builds on risky findings—to continuously surface such issues during development.

Related CWEs: inputValidation

CWE IDNameSeverity
CWE-20Improper Input Validation HIGH
CWE-22Path Traversal HIGH
CWE-74Injection CRITICAL
CWE-77Command Injection CRITICAL
CWE-78OS Command Injection CRITICAL
CWE-79Cross-site Scripting (XSS) HIGH
CWE-89SQL Injection CRITICAL
CWE-90LDAP Injection HIGH
CWE-91XML Injection HIGH
CWE-94Code Injection CRITICAL

Frequently Asked Questions

Does DynamoDB itself introduce command injection risks?
No. DynamoDB is a NoSQL database and does not execute shell commands. The risk arises when application code uses untrusted data from DynamoDB to construct and execute operating system commands.
How can I test my Fastapi endpoints for command injection during development?
Use the middleBrick CLI to scan your API: run middlebrick scan <your-api-url>. The scan performs black-box testing, including checks for injection-like behaviors, and provides prioritized findings with remediation guidance without requiring authentication or configuration.