HIGH symlink attackfastapiapi keys

Symlink Attack in Fastapi with Api Keys

Symlink Attack in Fastapi with Api Keys — how this specific combination creates or exposes the vulnerability

A symlink attack in a FastAPI service that uses API keys can occur when user-controlled input influences file system operations and the API key is treated as the sole gatekeeper. For example, an endpoint that downloads user-provided filenames may resolve paths via os.path.realpath or Path.resolve() without canonicalization, allowing an attacker to traverse directories and point to sensitive files. If the endpoint validates only the presence of a valid API key, the attacker can leverage symbolic links to read or overwrite files the key-holder is not intended to access.

Consider a FastAPI route that serves files from a user-specific upload directory:

import os
from fastapi import FastAPI, Header, HTTPException
from fastapi.security import APIKeyHeader

app = FastAPI()
api_key_header = APIKeyHeader(name='X-API-Key')

BASE = '/var/app/uploads'

@app.get('/files/{filename}')
def read_file(filename: str, x_api_key: str = api_key_header):
    # naive key check only
    if not validate_key(x_api_key):
        raise HTTPException(status_code=403, detail='Invalid API key')
    # unsafe path join + resolve
    full_path = os.path.realpath(os.path.join(BASE, filename))
    if not full_path.startswith(os.path.realpath(BASE)):
        raise HTTPException(status_code=400, detail='Invalid path')
    # ... read file
    return {'path': full_path}

An attacker can supply a filename such as ../../../etc/passwd (or use directory traversal sequences) and, if the path resolves outside BASE, the API key check passes while the resolved location exposes a sensitive file. The API key here does not enforce authorization boundaries; it only confirms the caller possesses a credential. The vulnerability is not in FastAPI itself but in the combination of path resolution, lack of strict path containment, and over-reliance on the API key for access control.

In a black-box scan, middleBrick tests controls like this by submitting path traversal patterns while providing a valid API key. It checks whether authorization is tied to the intended scope and whether path canonicalization is applied consistently. Even when API keys protect endpoints, insecure file handling can bypass intended access restrictions, leading to information disclosure or unintended file operations.

Api Keys-Specific Remediation in Fastapi — concrete code fixes

Remediation centers on strict path validation and avoiding reliance on the API key for path-level authorization. Always resolve and compare paths on the server side, enforce a strict base directory, and avoid returning filesystem details to the client.

Here is a hardened version of the earlier route:

import os
from pathlib import Path
from fastapi import FastAPI, Header, HTTPException
from fastapi.security import APIKeyHeader

app = FastAPI()
api_key_header = APIKeyHeader(name='X-API-Key')

BASE = Path('/var/app/uploads').resolve()

def validate_key(key: str) -> bool:
    # placeholder: implement your key validation logic
    return key == 'SECRET'

@app.get('/files/{filename}')
def read_file(filename: str, x_api_key: str = api_key_header):
    if not validate_key(x_api_key):
        raise HTTPException(status_code=403, detail='Invalid API key')
    # Normalize and restrict to BASE
    requested = Path(filename).name  # strip directory components
    full_path = (BASE / requested).resolve()
    try:
        full_path.relative_to(BASE)
    except ValueError:
        raise HTTPException(status_code=400, detail='Invalid path')
    if not full_path.is_file():
        raise HTTPException(status_code=404, detail='Not found')
    # Serve file content safely
    return {'path': str(full_path)}

Key changes:

  • Use Path.name to strip directory components from the user input, preventing traversal regardless of how many .. sequences are supplied.
  • Resolve the base directory once at startup and use Path.relative_to to ensure the final path remains inside the intended directory.
  • Do not expose resolved paths or filesystem metadata in responses; return only safe identifiers or content.

For API key management, consider scope-bound keys and additional authorization checks (e.g., mapping keys to allowed subpaths or tenant IDs). middleBrick can detect whether responses leak filesystem information and whether path validation is performed server-side, even when API keys are present.

Frequently Asked Questions

Can using API keys alone prevent symlink attacks in FastAPI?
No. API keys authenticate the caller but do not enforce path-level authorization. Without strict path canonicalization and containment checks, attackers can use symlink traversal to access files outside the intended directory even when a valid API key is supplied.
What should I validate in FastAPI file endpoints to avoid symlink risks?
Validate and sanitize user-supplied paths, resolve base and final paths server-side with Path.resolve(), enforce strict containment with relative_to, avoid user-controlled directory traversal, and never expose raw filesystem paths in responses.