FastAPI
Security testing for FastAPI/Starlette applications. Focus on dependency injection flaws, middleware gaps, and authorization drift across routers and channels.
Attack Surface
Core Components
- ASGI middlewares: CORS, TrustedHost, ProxyHeaders, Session, exception handlers, lifespan events
- Routers and sub-apps: APIRouter prefixes/tags, mounted apps (StaticFiles, admin),
include_router, versioned paths
- Dependency injection:
Depends, Security, OAuth2PasswordBearer, HTTPBearer, scopes
Data Handling
- Pydantic models: v1/v2, unions/Annotated, custom validators, extra fields policy, coercion
- File operations: UploadFile, File, FileResponse, StaticFiles mounts
- Templates: Jinja2Templates rendering
Channels
- HTTP (sync/async), WebSocket, SSE/StreamingResponse
- BackgroundTasks and task queues
Deployment
- Uvicorn/Gunicorn, reverse proxies/CDN, TLS termination, header trust
High-Value Targets
/openapi.json, /docs, /redoc in production (full attack surface map, securitySchemes, server URLs)
- Auth flows: token endpoints, session/cookie bridges, OAuth device/PKCE
- Admin/staff routers, feature-flagged routes,
include_in_schema=False endpoints
- File upload/download, import/export/report endpoints, signed URL generators
- WebSocket endpoints (notifications, admin channels, commands)
- Background job endpoints (
/jobs/{id}, /tasks/{id}/result)
- Mounted subapps (admin UI, storage browsers, metrics/health)
Reconnaissance
OpenAPI Mining
GET /openapi.json
GET /docs
GET /redoc
GET /api/openapi.json
GET /internal/openapi.json
Extract: paths, parameters, securitySchemes, scopes, servers. Endpoints with include_in_schema=False won't appear—fuzz based on discovered prefixes and common admin/debug names.
Dependency Mapping
For each route, identify:
- Router-level dependencies (applied to all routes)
- Route-level dependencies (per endpoint)
- Which dependencies enforce auth vs just parse input
Key Vulnerabilities
Authentication & Authorization
Dependency Injection Gaps
- Routes missing security dependencies present on other routes
Depends used instead of Security (ignores scope enforcement)
- Token presence treated as authentication without signature verification
OAuth2PasswordBearer only yields a token string—verify routes don't treat presence as auth
JWT Misuse
- Decode without verify: test unsigned tokens, attacker-signed tokens
- Algorithm confusion: HS256/RS256 cross-use if not pinned
kid header injection for custom key lookup paths
- Missing issuer/audience validation, cross-service token reuse
Session Weaknesses
- SessionMiddleware with weak
secret_key
- Session fixation via predictable signing
- Cookie-based auth without CSRF protection
OAuth/OIDC
- Device/PKCE flows: verify strict PKCE S256 and state/nonce enforcement
Access Control
IDOR via Dependencies
- Object IDs in path/query not validated against caller
- Tenant headers trusted without binding to authenticated user
- BackgroundTasks acting on IDs without re-validating ownership at execution time
- Export/import pipelines with IDOR and cross-tenant leaks
Scope Bypass
- Minimal scope satisfaction (any valid token accepted)
- Router vs route scope enforcement inconsistency
Input Handling
Pydantic Exploitation
- Type coercion: strings to ints/bools, empty strings to None, truthiness edge cases
- Extra fields:
extra = "allow" permits injecting control fields (role, ownerId, scope)
- Union types and
Annotated: craft shapes hitting unintended validation branches
Content-Type Switching
application/json ↔ application/x-www-form-urlencoded ↔ multipart/form-data
Different content types hit different validators or code paths (parser differentials).
Parameter Manipulation
- Case variations in header/cookie names
- Duplicate parameters exploiting DI precedence
- Method override via
X-HTTP-Method-Override (upstream respects, app doesn't)
CORS & CSRF
CORS Misconfiguration
- Overly broad
allow_origin_regex
- Origin reflection without validation
- Credentialed requests with permissive origins
- Verify preflight vs actual request deltas
CSRF Exposure
- No built-in CSRF in FastAPI/Starlette
- Cookie-based auth without origin validation
- Missing SameSite attribute
Proxy & Host Trust
Header Spoofing
- ProxyHeadersMiddleware without network boundary: spoof
X-Forwarded-For/Proto to influence auth/IP gating
- Absent TrustedHostMiddleware: Host header poisoning in password reset links, absolute URL generation
- Cache key confusion: missing Vary on Authorization/Cookie/Tenant
Server-Side Vulnerabilities
Template Injection (Jinja2)
{{7*7}} # Arithmetic confirmation
{{cycler.__init__.__globals__['os'].popen('id').read()}} # RCE
Check autoescape settings and custom filters/globals.
SSRF
- User-supplied URLs in imports, previews, webhooks validation
- Test: loopback, RFC1918, IPv6, redirects, DNS rebinding, header control
- Library behavior (httpx/requests): redirect policy, header forwarding, protocol support
- Protocol smuggling:
file://, ftp://, gopher-like shims if custom clients
File Upload
- Path traversal in
UploadFile.filename with control characters
- Missing storage root enforcement, symlink following
- Vary filename encodings, dot segments, NUL-like bytes
- Verify storage paths and served URLs
WebSocket Security
- Missing per-connection authentication
- Cross-origin WebSocket without origin validation
- Topic/channel IDOR (subscribing to other users' channels)
- Authorization only at handshake, not per-message
Mounted Apps
Sub-apps at /admin, /static, /metrics may bypass global middlewares. Verify auth enforcement parity across all mounts.
Alternative Stacks
- If GraphQL (Strawberry/Graphene) is mounted: validate resolver-level authorization, IDOR on node/global IDs
- If SQLModel/SQLAlchemy present: probe for raw query usage and row-level authorization gaps
Bypass Techniques
- Content-type switching to traverse alternate validators
- Parameter duplication and case variants exploiting DI precedence
- Method confusion via proxies (
X-HTTP-Method-Override)
- Race windows around dependency-validated state transitions (issue token then mutate with parallel requests)
Testing Methodology
- Enumerate - Fetch OpenAPI, diff with 404-fuzzing for hidden endpoints
- Matrix testing - Test each route across: unauth/user/admin × HTTP/WebSocket × JSON/form/multipart
- Dependency analysis - Map which dependencies enforce auth vs parse input
- Cross-environment - Compare dev/stage/prod for middleware and docs exposure differences
- Channel consistency - Verify same authorization on HTTP and WebSocket for equivalent operations
Validation Requirements
- Side-by-side requests showing unauthorized access (owner vs non-owner, cross-tenant)
- Cross-channel proof (HTTP and WebSocket for same rule)
- Header/proxy manipulation showing altered outcomes (Host/XFF/CORS)
- Minimal payloads for template injection, SSRF, token misuse with safe/OAST oracles
- Document exact dependency paths (router-level, route-level) that missed enforcement
Source: n1majne3/strix — distributed by TomeVault.
1---2name: fastapi-43description: Security testing playbook for FastAPI applications covering ASGI, dependency injection, and API vulnerabilities Use when this capability is needed.4---5# FastAPI67Security testing for FastAPI/Starlette applications. Focus on dependency injection flaws, middleware gaps, and authorization drift across routers and channels.89## Attack Surface1011**Core Components**12- ASGI middlewares: CORS, TrustedHost, ProxyHeaders, Session, exception handlers, lifespan events13- Routers and sub-apps: APIRouter prefixes/tags, mounted apps (StaticFiles, admin), `include_router`, versioned paths14- Dependency injection: `Depends`, `Security`, `OAuth2PasswordBearer`, `HTTPBearer`, scopes1516**Data Handling**17- Pydantic models: v1/v2, unions/Annotated, custom validators, extra fields policy, coercion18- File operations: UploadFile, File, FileResponse, StaticFiles mounts19- Templates: Jinja2Templates rendering2021**Channels**22- HTTP (sync/async), WebSocket, SSE/StreamingResponse23- BackgroundTasks and task queues2425**Deployment**26- Uvicorn/Gunicorn, reverse proxies/CDN, TLS termination, header trust2728## High-Value Targets2930- `/openapi.json`, `/docs`, `/redoc` in production (full attack surface map, securitySchemes, server URLs)31- Auth flows: token endpoints, session/cookie bridges, OAuth device/PKCE32- Admin/staff routers, feature-flagged routes, `include_in_schema=False` endpoints33- File upload/download, import/export/report endpoints, signed URL generators34- WebSocket endpoints (notifications, admin channels, commands)35- Background job endpoints (`/jobs/{id}`, `/tasks/{id}/result`)36- Mounted subapps (admin UI, storage browsers, metrics/health)3738## Reconnaissance3940**OpenAPI Mining**41```42GET /openapi.json43GET /docs44GET /redoc45GET /api/openapi.json46GET /internal/openapi.json47```4849Extract: paths, parameters, securitySchemes, scopes, servers. Endpoints with `include_in_schema=False` won't appear—fuzz based on discovered prefixes and common admin/debug names.5051**Dependency Mapping**5253For each route, identify:54- Router-level dependencies (applied to all routes)55- Route-level dependencies (per endpoint)56- Which dependencies enforce auth vs just parse input5758## Key Vulnerabilities5960### Authentication & Authorization6162**Dependency Injection Gaps**63- Routes missing security dependencies present on other routes64- `Depends` used instead of `Security` (ignores scope enforcement)65- Token presence treated as authentication without signature verification66- `OAuth2PasswordBearer` only yields a token string—verify routes don't treat presence as auth6768**JWT Misuse**69- Decode without verify: test unsigned tokens, attacker-signed tokens70- Algorithm confusion: HS256/RS256 cross-use if not pinned71- `kid` header injection for custom key lookup paths72- Missing issuer/audience validation, cross-service token reuse7374**Session Weaknesses**75- SessionMiddleware with weak `secret_key`76- Session fixation via predictable signing77- Cookie-based auth without CSRF protection7879**OAuth/OIDC**80- Device/PKCE flows: verify strict PKCE S256 and state/nonce enforcement8182### Access Control8384**IDOR via Dependencies**85- Object IDs in path/query not validated against caller86- Tenant headers trusted without binding to authenticated user87- BackgroundTasks acting on IDs without re-validating ownership at execution time88- Export/import pipelines with IDOR and cross-tenant leaks8990**Scope Bypass**91- Minimal scope satisfaction (any valid token accepted)92- Router vs route scope enforcement inconsistency9394### Input Handling9596**Pydantic Exploitation**97- Type coercion: strings to ints/bools, empty strings to None, truthiness edge cases98- Extra fields: `extra = "allow"` permits injecting control fields (role, ownerId, scope)99- Union types and `Annotated`: craft shapes hitting unintended validation branches100101**Content-Type Switching**102```103application/json ↔ application/x-www-form-urlencoded ↔ multipart/form-data104```105Different content types hit different validators or code paths (parser differentials).106107**Parameter Manipulation**108- Case variations in header/cookie names109- Duplicate parameters exploiting DI precedence110- Method override via `X-HTTP-Method-Override` (upstream respects, app doesn't)111112### CORS & CSRF113114**CORS Misconfiguration**115- Overly broad `allow_origin_regex`116- Origin reflection without validation117- Credentialed requests with permissive origins118- Verify preflight vs actual request deltas119120**CSRF Exposure**121- No built-in CSRF in FastAPI/Starlette122- Cookie-based auth without origin validation123- Missing SameSite attribute124125### Proxy & Host Trust126127**Header Spoofing**128- ProxyHeadersMiddleware without network boundary: spoof `X-Forwarded-For/Proto` to influence auth/IP gating129- Absent TrustedHostMiddleware: Host header poisoning in password reset links, absolute URL generation130- Cache key confusion: missing Vary on Authorization/Cookie/Tenant131132### Server-Side Vulnerabilities133134**Template Injection (Jinja2)**135```python136{{7*7}} # Arithmetic confirmation137{{cycler.__init__.__globals__['os'].popen('id').read()}} # RCE138```139Check autoescape settings and custom filters/globals.140141**SSRF**142- User-supplied URLs in imports, previews, webhooks validation143- Test: loopback, RFC1918, IPv6, redirects, DNS rebinding, header control144- Library behavior (httpx/requests): redirect policy, header forwarding, protocol support145- Protocol smuggling: `file://`, `ftp://`, gopher-like shims if custom clients146147**File Upload**148- Path traversal in `UploadFile.filename` with control characters149- Missing storage root enforcement, symlink following150- Vary filename encodings, dot segments, NUL-like bytes151- Verify storage paths and served URLs152153### WebSocket Security154155- Missing per-connection authentication156- Cross-origin WebSocket without origin validation157- Topic/channel IDOR (subscribing to other users' channels)158- Authorization only at handshake, not per-message159160### Mounted Apps161162Sub-apps at `/admin`, `/static`, `/metrics` may bypass global middlewares. Verify auth enforcement parity across all mounts.163164### Alternative Stacks165166- If GraphQL (Strawberry/Graphene) is mounted: validate resolver-level authorization, IDOR on node/global IDs167- If SQLModel/SQLAlchemy present: probe for raw query usage and row-level authorization gaps168169## Bypass Techniques170171- Content-type switching to traverse alternate validators172- Parameter duplication and case variants exploiting DI precedence173- Method confusion via proxies (`X-HTTP-Method-Override`)174- Race windows around dependency-validated state transitions (issue token then mutate with parallel requests)175176## Testing Methodology1771781. **Enumerate** - Fetch OpenAPI, diff with 404-fuzzing for hidden endpoints1792. **Matrix testing** - Test each route across: unauth/user/admin × HTTP/WebSocket × JSON/form/multipart1803. **Dependency analysis** - Map which dependencies enforce auth vs parse input1814. **Cross-environment** - Compare dev/stage/prod for middleware and docs exposure differences1825. **Channel consistency** - Verify same authorization on HTTP and WebSocket for equivalent operations183184## Validation Requirements185186- Side-by-side requests showing unauthorized access (owner vs non-owner, cross-tenant)187- Cross-channel proof (HTTP and WebSocket for same rule)188- Header/proxy manipulation showing altered outcomes (Host/XFF/CORS)189- Minimal payloads for template injection, SSRF, token misuse with safe/OAST oracles190- Document exact dependency paths (router-level, route-level) that missed enforcement191192---193> Source: [n1majne3/strix](https://github.com/n1majne3/strix) — distributed by [TomeVault](https://tomevault.io).194<!-- tomevault:4.0:skill_md:2026-05-22 -->