HIGH command injectionfastapibasic auth

Command Injection in Fastapi with Basic Auth

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

Command Injection occurs when untrusted input is concatenated into a system command, allowing an attacker to execute arbitrary shell commands. In Fastapi, this risk can emerge even when the endpoint is protected by HTTP Basic Authentication. Basic Auth provides a transport-level identity check but does not sanitize or validate command arguments. If user-controlled data (e.g., a username, header, or query parameter) is passed to a subprocess call without proper validation or escaping, the boundary between identity and authorization blurs: authentication confirms who is making the request, but does nothing to prevent that authenticated user from supplying malicious input that reaches the shell.

A typical pattern is an authenticated endpoint that invokes a system utility using Python’s subprocess module. For example, an endpoint might accept a filename via a query parameter and pass it to tar or grep. If the parameter is used in a shell command string without escaping, an authenticated attacker can inject additional shell commands using shell metacharacters such as &&, ;, or backticks. Because the endpoint requires a valid username and password, the attacker must first obtain credentials (or use a leaked set), but once authenticated, the unsafe command construction enables privilege escalation, data exfiltration, or further network pivoting within the runtime environment.

In a black-box scan, middleBrick’s checks for Authentication and Unsafe Consumption run in parallel. The scanner first validates that Basic Auth is required and that credentials are necessary to reach the endpoint. It then probes the endpoint with authenticated requests, attempting to inject command sequences via input vectors that reach subprocess calls or OS utilities. If the API reflects injected output or changes system state without validation, the scan surfaces an Unsafe Consumption finding mapped to the Authentication context, highlighting that identity enforcement does not equate to input safety.

Basic Auth-Specific Remediation in Fastapi — concrete code fixes

Remediation focuses on removing shell interpretation of untrusted data and enforcing strict input validation. Do not rely on Basic Auth alone to secure command execution. Instead, avoid shell=True, use parameterized APIs, and validate input against an allowlist.

Example: Unsafe endpoint with Basic Auth (vulnerable)

from fastapi import FastAPI, Depends, HTTPException, Header
import subprocess
import shlex

app = FastAPI()

def get_current_user(authorization: str = Header(...)):
    # Simplified Basic Auth check for example
    if not authorization.startswith("Basic "):
        raise HTTPException(status_code=401, detail="Unauthorized")
    # In real code, decode and validate credentials
    return {"username": "alice"}

@app.get("/archive")
def list_files(name: str, user: dict = Depends(get_current_user)):
    # UNSAFE: shell=True with unsanitized input
    result = subprocess.run(f"tar -tf {name}", shell=True, capture_output=True, text=True)
    return {"output": result.stdout}

In the above, an authenticated user can supply name=file.tar;cat%20/etc/passwd and execute arbitrary commands. Basic Auth is present but does not mitigate command injection.

Example: Secured endpoint with validation and no shell

from fastapi import FastAPI, Depends, HTTPException, Header
import subprocess

app = FastAPI()

def get_current_user(authorization: str = Header(...)):
    if not authorization.startswith("Basic "):
        raise HTTPException(status_code=401, detail="Unauthorized")
    return {"username": "alice"}

ALLOWED_NAMES = {"backup", "report", "logs"}

@app.get("/archive")
def list_files(name: str, user: dict = Depends(get_current_user)):
    # Validate input against an allowlist
    if name not in ALLOWED_NAMES:
        raise HTTPException(status_code=400, detail="Invalid archive name")
    # Use a list, shell=False (default) to avoid shell interpretation
    result = subprocess.run(["tar", "-tf", name], capture_output=True, text=True, timeout=10)
    return {"output": result.stdout}

If you must construct command-like arguments dynamically, use shlex.quote on each argument and keep shell=False, but prefer an allowlist as shown. Basic Auth remains useful for identity, but input validation and safe subprocess usage are required to prevent command injection.

Example: Using shlex.quote when dynamic arguments are unavoidable

import shlex
cmd = ["tar", "-tf", shlex.quote(name)]
subprocess.run(cmd, capture_output=True)

These patterns align with secure coding practices and map to findings in the BFLA/Privilege Escalation and Input Validation checks, which run alongside Authentication in middleBrick scans.

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 Basic Auth prevent command injection in Fastapi APIs?
No. Basic Auth confirms identity but does not sanitize inputs. Command injection is prevented by avoiding shell metacharacters, using parameterized subprocess calls, and validating input with an allowlist.
How does middleBrick detect command injection in authenticated endpoints?
middleBrick tests the unauthenticated attack surface and, when Basic Auth is required, authenticates first then probes inputs that reach subprocess or OS utilities. Findings combine Authentication presence with Unsafe Consumption checks to highlight command injection risks.