HIGH container escapefastapi

Container Escape in Fastapi

How Container Escape Manifests in Fastapi

Container escape in Fastapi applications typically occurs when attackers can manipulate file paths, environment variables, or system calls to break out of the container's isolation. Fastapi's async nature and Python's dynamic features create specific attack vectors that differ from traditional web frameworks.

One common pattern involves path traversal vulnerabilities in file upload or download endpoints. Consider this Fastapi endpoint:

@app.get("/download/")
async def download_file(filename: str):
    with open(filename, 'rb') as f:
        return StreamingResponse(f, media_type='application/octet-stream')

An attacker can request /download/../../../../etc/passwd to read files outside the container's intended directory. Fastapi's dependency injection system doesn't automatically sanitize path parameters, making this a frequent issue.

Another Fastapi-specific vector involves improper use of subprocess with user-controlled input:

@app.post("/run/")
async def run_command(command: str = Form(...)):
    result = await asyncio.create_subprocess_shell(
        command,
        stdout=asyncio.subprocess.PIPE,
        stderr=asyncio.subprocess.PIPE
    )
    stdout, stderr = await result.communicate()
    return JSONResponse({'output': stdout.decode()})

This async subprocess execution allows command injection that can mount host volumes or access Docker sockets. The /var/run/docker.sock is particularly dangerous as it provides API access to the Docker daemon, enabling container escape through container management APIs.

Environment variable manipulation is another Fastapi-specific concern. Fastapi applications often read configuration from environment variables:

@app.get("/config/")
async def get_config():
    db_url = os.getenv('DATABASE_URL', 'sqlite:///./test.db')
    return JSONResponse({'db_url': db_url})

If an attacker can influence these environment variables through container runtime configuration or supply chain attacks, they can redirect database connections to host system services or manipulate application behavior.

Fastapi's background tasks and async workers also introduce container escape risks. Background tasks run in separate contexts and may have different filesystem permissions:

@app.post("/upload/")
async def upload_file(file: UploadFile = File(...)):
    await asyncio.to_thread(process_file, file.filename, await file.read())
    return JSONResponse({'status': 'uploaded'})

If process_file performs unsafe operations or if the background task has elevated privileges, attackers can exploit timing windows to access host resources.

Fastapi-Specific Detection

Detecting container escape vulnerabilities in Fastapi requires examining both the application code and runtime configuration. Static analysis tools often miss Fastapi-specific patterns due to its async/await syntax and dependency injection system.

middleBrick's scanning approach identifies Fastapi-specific container escape patterns by analyzing the runtime behavior of API endpoints. The scanner tests for path traversal by attempting to access known sensitive files:

# middleBrick would test these patterns automatically:
/download/../../../../etc/passwd
/download/./%2Fetc%2Fpasswd
/download/C:/Windows/win.ini

The scanner also tests for command injection vulnerabilities by sending payloads that attempt to execute system commands through Fastapi's async subprocess handling:

; cat /etc/passwd #
echo "test" && cat /etc/shadow
echo $(whoami)

For Fastapi applications using background tasks, middleBrick analyzes the async task patterns to identify potential privilege escalation paths. The scanner checks if background tasks have access to Docker sockets or other host resources:

# Testing for Docker socket access
curl -s http://localhost:2375/version

middleBrick's OpenAPI spec analysis is particularly effective for Fastapi applications since Fastapi automatically generates OpenAPI specifications. The scanner cross-references the spec with runtime findings to identify endpoints that accept file paths or execute commands:

{
  "paths": {
    "/download/{filename}": {
      "get": {
        "parameters": [
          {
            "name": "filename",
            "in": "path",
            "schema": { "type": "string" }
          }
        ]
      }
    }
  }
}

The scanner flags path parameters that could allow directory traversal and checks if file operations use safe path joining methods. It also tests for unsafe consumption patterns where Fastapi endpoints accept arbitrary data that could be executed or interpreted as code.

middleBrick's LLM/AI security checks are relevant for Fastapi applications using AI features. The scanner tests for system prompt leakage and prompt injection vulnerabilities that could be used to manipulate Fastapi's AI-powered features to execute unauthorized commands or access sensitive data.

Fastapi-Specific Remediation

Remediating container escape vulnerabilities in Fastapi requires a defense-in-depth approach combining secure coding practices with proper container configuration. Fastapi's async nature requires specific considerations for security.

For path traversal vulnerabilities, use Fastapi's path validation and safe path joining:

from fastapi import FastAPI, HTTPException
from pathlib import Path
import aiofiles

app = FastAPI()

BASE_DIR = Path("/app/data")

@app.get("/download/")
async def download_file(filename: str):
    # Validate and sanitize the path
    requested_path = Path(filename).resolve()
    base_path = BASE_DIR.resolve()
    
    if not requested_path.is_relative_to(base_path):
        raise HTTPException(status_code=400, detail="Invalid file path")
    
    if not requested_path.exists():
        raise HTTPException(status_code=404, detail="File not found")
    
    async with aiofiles.open(requested_path, 'rb') as f:
        return StreamingResponse(await f.read(), media_type='application/octet-stream')

This approach uses pathlib.Path.resolve() to get the absolute path and is_relative_to() to ensure the requested file stays within the base directory. Fastapi's type hints help document the expected input format.

For command injection prevention, avoid subprocess entirely or use strict whitelisting:

from fastapi import FastAPI, HTTPException
import shlex

app = FastAPI()

ALLOWED_COMMANDS = {
    'ls': ['/app/data'],
    'cat': ['/app/data']
}

@app.post("/run/")
async def run_command(command: str = Form(...)):
    parts = shlex.split(command)
    cmd = parts[0]
    
    if cmd not in ALLOWED_COMMANDS:
        raise HTTPException(status_code=400, detail="Command not allowed")
    
    # Additional validation for arguments
    if len(parts) > 1:
        raise HTTPException(status_code=400, detail="Arguments not allowed")
    
    # Use a safe execution method
    try:
        result = await asyncio.create_subprocess_exec(
            cmd,
            stdout=asyncio.subprocess.PIPE,
            stderr=asyncio.subprocess.PIPE
        )
        stdout, stderr = await result.communicate()
        return JSONResponse({'output': stdout.decode()})
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

This implementation uses shlex.split() for proper command parsing and validates against a whitelist of allowed commands. The asyncio.create_subprocess_exec() method is safer than create_subprocess_shell() as it doesn't invoke a shell.

For Fastapi applications using background tasks, implement proper isolation and input validation:

from fastapi import BackgroundTasks
from pydantic import BaseModel
from typing import Any

class FileUpload(BaseModel):
    filename: str
    content: bytes

@app.post("/upload/")
async def upload_file(
    file: UploadFile = File(...),
    background_tasks: BackgroundTasks = BackgroundTasks()
):
    content = await file.read()
    background_tasks.add_task(
        process_file_safely,
        file.filename,
        content
    )
    return JSONResponse({'status': 'processing'})

async def process_file_safely(filename: str, content: bytes):
    # Validate filename
    safe_filename = filename.replace('..', '').replace('/', '_')
    safe_path = BASE_DIR / safe_filename
    
    # Write file safely
    async with aiofiles.open(safe_path, 'wb') as f:
        await f.write(content)

This pattern uses Pydantic models for input validation and ensures background tasks operate on sanitized data. The BackgroundTasks dependency injection makes it clear which endpoints use async processing.

Container runtime configuration is equally important. Use read-only filesystems where possible, drop unnecessary capabilities, and avoid running as root:

FROM python:3.11-slim

WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# Create non-root user
RUN addgroup --system appgroup && adduser --system --group appgroup appuser
USER appuser

# Create data directory with proper permissions
RUN mkdir -p /app/data && chown appuser:appgroup /app/data

# Use read-only filesystem except for data
VOLUME /app/data

EXPOSE 8000

CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]

Combine these code-level fixes with proper container security contexts in your orchestration configuration to prevent container escape even if application vulnerabilities exist.

Frequently Asked Questions

How does Fastapi's async nature affect container escape vulnerabilities?
Fastapi's async/await syntax and background task system create unique timing and context-related vulnerabilities. Background tasks may run with different filesystem permissions or access to resources than the main request context. The async subprocess execution in Fastapi can also introduce race conditions where attackers can manipulate system resources during task execution. middleBrick's scanning specifically tests these async patterns by analyzing the OpenAPI spec for background task endpoints and testing their behavior under concurrent load.
Can middleBrick detect container escape vulnerabilities in Fastapi applications?
Yes, middleBrick scans Fastapi applications for container escape patterns including path traversal in file endpoints, command injection through async subprocess calls, and unsafe background task execution. The scanner tests for known sensitive file access attempts, Docker socket exposure, and environment variable manipulation. middleBrick's OpenAPI analysis identifies Fastapi-specific patterns like path parameters that could allow directory traversal and endpoints that accept arbitrary file names. The scanner provides specific findings with severity levels and remediation guidance tailored to Fastapi's async architecture.