HIGH prototype pollutionfastapi

Prototype Pollution in Fastapi

How Prototype Pollution Manifests in Fastapi

Prototype Pollution in Fastapi applications occurs when untrusted data modifies JavaScript object prototypes, leading to unexpected behavior in Python-JavaScript bridges or when Fastapi interacts with JavaScript-based systems. This vulnerability is particularly relevant in Fastapi applications that handle JSON payloads or interact with JavaScript frontends.

The most common attack vector in Fastapi is through nested JSON objects where attackers exploit JavaScript's prototype chain. Consider this Fastapi endpoint:

from fastapi import FastAPI, Request
app = FastAPI()

@app.post("/process-data")
def process_data(request: Request):
    data = await request.json()
    # Process nested data
    result = data.get("user", {}).get("profile", {})
    return result

An attacker can send a payload like:

{
  "user": {
    "__proto__": {
      "isAdmin": true
    }
  }
}

In JavaScript environments, this would modify Object.prototype.isAdmin. While Python doesn't have prototype chains, Fastapi applications often serialize/deserialize data to/from JSON for JavaScript consumption, creating a bridge where prototype pollution can manifest.

Fastapi's dependency injection system can also be affected. Consider:

from fastapi import Depends

def get_user_info(user_data: dict = Depends()) -> dict:
    # User data comes from request body
    return user_data

@app.post("/user-profile")
def user_profile(user_info: dict = Depends(get_user_info)):
    if user_info.get("isAdmin"):
        return admin_dashboard()
    return user_dashboard()

If an attacker can manipulate the prototype chain through the dependency injection, they might bypass authorization checks.

Another Fastapi-specific scenario involves Pydantic models. Fastapi uses Pydantic for data validation, and prototype pollution can affect model behavior:

from fastapi import FastAPI
from pydantic import BaseModel

class UserProfile(BaseModel):
    username: str
    email: str

@app.post("/create-user")
def create_user(profile: UserProfile):
    # Process user profile
    return profile.dict()

An attacker might try to exploit Pydantic's model validation by sending unexpected prototype properties that could affect validation logic or default values.

Fastapi-Specific Detection

Detecting Prototype Pollution in Fastapi applications requires both static code analysis and runtime monitoring. Here are Fastapi-specific detection strategies:

Input Validation with Pydantic Models

Fastapi's Pydantic integration provides the first line of defense. Create strict models that reject unexpected fields:

from pydantic import BaseModel, Field, ValidationError
from typing import Any

class StrictProfile(BaseModel):
    username: str = Field(..., regex="^[a-zA-Z0-9_.-]{3,30}$")
    email: str = Field(..., regex="^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$")
    class Config:
        extra = "forbid"  # Reject any fields not explicitly defined

The extra = "forbid" setting prevents prototype pollution by rejecting unexpected properties.

Custom Request Parsing

Implement custom request parsing to detect suspicious patterns:

import re
from fastapi import Request, HTTPException

PROTO_PATTERN = re.compile(r"__(proto|constructor)__", re.IGNORECASE)

async def safe_json_request(request: Request):
    data = await request.json()
    if contains_prototype_pollution(data):
        raise HTTPException(status_code=400, detail="Invalid request format")
    return data

def contains_prototype_pollution(obj, path=""):
    if isinstance(obj, dict):
        for key, value in obj.items():
            current_path = f"{path}.{key}" if path else key
            if PROTO_PATTERN.search(key):
                return True
            if contains_prototype_pollution(value, current_path):
                return True
    elif isinstance(obj, list):
        for index, item in enumerate(obj):
            if contains_prototype_pollution(item, f"{path}[{index}]"):
                return True
    return False

Using middleBrick for Automated Detection

middleBrick's black-box scanning can detect Prototype Pollution vulnerabilities in Fastapi applications without requiring source code access. The scanner tests for:

  • Prototype chain manipulation attempts in JSON payloads
  • Unexpected property injection in API responses
  • Authorization bypass through prototype manipulation
  • Input validation bypass patterns

To scan your Fastapi API with middleBrick:

# Using the CLI
middlebrick scan https://your-fastapi-app.com/api/ --output report.json

# Or in CI/CD
middlebrick scan https://your-fastapi-app.com/api/ --fail-threshold C

middleBrick specifically tests Fastapi's JSON handling by sending crafted payloads that attempt prototype pollution and analyzing the responses for successful manipulation.

Fastapi-Specific Remediation

Remediating Prototype Pollution in Fastapi applications requires a defense-in-depth approach. Here are Fastapi-specific solutions:

Strict Pydantic Models

The most effective defense is using strict Pydantic models with proper configuration:

from pydantic import BaseModel, Field, validator
from typing import Any

class SecureUserProfile(BaseModel):
    username: str
    email: str
    
    @validator('username')
    def validate_username(cls, v):
        if not isinstance(v, str):
            raise ValueError('Username must be a string')
        if not re.match(r'^[a-zA-Z0-9_.-]{3,30}$', v):
            raise ValueError('Invalid username format')
        return v
    
    @validator('email')
    def validate_email(cls, v):
        if not isinstance(v, str):
            raise ValueError('Email must be a string')
        if not re.match(r'^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$', v):
            raise ValueError('Invalid email format')
        return v
    
    class Config:
        extra = "forbid"  # Reject any extra fields
        allow_population_by_field_name = True
        arbitrary_types_allowed = False

Request Body Sanitization

Implement middleware to sanitize incoming requests:

from fastapi import Request, HTTPException, Middleware
from fastapi.middleware import Middleware

class PrototypePollutionMiddleware:
    def __init__(self, app):
        self.app = app
    
    async def __call__(self, request: Request, call_next):
        if request.method in ['POST', 'PUT', 'PATCH']:
            try:
                body = await request.json()
                if contains_prototype_pollution(body):
                    raise HTTPException(status_code=400, detail="Prototype pollution detected")
            except Exception:
                pass  # Not JSON, skip validation
        
        response = await call_next(request)
        return response

app.add_middleware(PrototypePollutionMiddleware)

Safe JSON Serialization

When returning data that originated from untrusted sources, ensure safe serialization:

from fastapi import FastAPI, Response
import json

app = FastAPI()

def safe_json_serialize(data):
    # Remove any prototype-like properties before serialization
    cleaned_data = remove_prototype_properties(data)
    return json.dumps(cleaned_data)

def remove_prototype_properties(obj):
    if isinstance(obj, dict):
        return {k: remove_prototype_properties(v) for k, v in obj.items() 
                if not PROTO_PATTERN.search(k)}
    elif isinstance(obj, list):
        return [remove_prototype_properties(item) for item in obj]
    else:
        return obj

@app.post("/safe-endpoint")
def safe_endpoint(data: dict):
    cleaned = remove_prototype_properties(data)
    return Response(content=safe_json_serialize(cleaned), media_type="application/json")

Continuous Monitoring with middleBrick

Integrate middleBrick into your Fastapi development workflow for ongoing protection:

# .github/workflows/security.yml
name: Security Scan
on: [push, pull_request]

jobs:
  security-scan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - name: Run middleBrick Scan
        run: |
          npm install -g middlebrick
          middlebrick scan ${{ secrets.API_URL }} \
            --fail-threshold B \
            --output security-report.json
      - name: Upload Report
        uses: actions/upload-artifact@v2
        with:
          name: security-report
          path: security-report.json

This GitHub Action scans your Fastapi API endpoints on every code change, ensuring prototype pollution vulnerabilities are caught early in the development cycle.

Frequently Asked Questions

How does Prototype Pollution differ between Fastapi and Node.js applications?
In Node.js, Prototype Pollution directly modifies JavaScript object prototypes since JavaScript has prototype-based inheritance. Fastapi applications don't have JavaScript prototypes, but they can be affected when handling JSON data that will be consumed by JavaScript frontends, or when Fastapi interacts with JavaScript-based systems. The attack surface is different: Fastapi needs to validate JSON inputs and outputs, while Node.js must protect against prototype chain manipulation at runtime.
Can middleBrick detect Prototype Pollution in Fastapi applications without source code access?
Yes, middleBrick uses black-box scanning to detect Prototype Pollution vulnerabilities in Fastapi applications. It sends crafted JSON payloads designed to trigger prototype pollution patterns, then analyzes the API responses for signs of successful manipulation. The scanner tests for prototype chain injection, unexpected property behavior, and authorization bypass attempts without needing access to your Fastapi source code.