Dangling Dns in Fastapi with Jwt Tokens
Dangling Dns in Fastapi with Jwt Tokens — how this specific combination creates or exposes the vulnerability
A dangling DNS record occurs when a hostname (e.g., internal.api.example.com) still points to an IP address, even though the associated service or infrastructure has been decommissioned. In a FastAPI application that relies on JWT tokens for authentication, this combination can expose security risks when the app performs network calls using runtime data derived from or influenced by the token’s claims.
FastAPI applications often validate JWT tokens and then use claims (such as tenant identifiers, subdomains, or hostnames) to construct further network requests. If a claim is attacker-influenced (e.g., via a compromised or forged JWT with a malicious host or origin claim), the application may resolve a dangling hostname. Because the DNS name still resolves, the request may be directed to an unintended host that the attacker controls or to a leftover internal service. This can lead to unauthorized data access, SSRF against internal endpoints, or redirection to malicious infrastructure. The risk is particularly relevant when token validation does not strictly scope what the application is allowed to request, and when runtime hostname resolution is based on token data without strict allowlisting.
Consider a FastAPI app that uses a JWT’s sub or a custom claim to select a backend service URL. If an attacker obtains a valid JWT (e.g., via theft or a low-privilege account) and modifies the claim to point to a dangling internal hostname like legacy-db.internal.example.com, the app may forward requests to that host. Because the DNS entry exists (perhaps pointing to a forgotten server), the request reaches an unintended endpoint. This scenario aligns with common API security weaknesses such as BOLA/IDOR when authorization checks are tied to token claims but network destinations are not rigorously validated.
middleBrick detects this class of risk by correlating OpenAPI/Swagger specifications (including $ref resolution) with runtime behavior. It flags scenarios where network calls are made using dynamic inputs derived from JWT claims without strict schema enforcement or allowlisting. The scanner runs active probes and pattern checks aligned with OWASP API Top 10 and common CWE categories, identifying places where token-derived data influences external resolution. By cross-referencing spec definitions with observed runtime calls, middleBrick surfaces these dangling DNS paths as high-priority findings, providing remediation guidance to tighten claim validation and network destination controls.
Jwt Tokens-Specific Remediation in Fastapi — concrete code fixes
To mitigate risks involving dangling DNS when using JWT tokens in FastAPI, enforce strict validation of token claims and avoid using attacker-influenced data to construct network destinations. Below are concrete, secure coding patterns.
1. Validate and scope JWT claims
Do not trust claims used for routing or host selection. Validate against an allowlist and bind claims to expected values per user or tenant.
from fastapi import Depends, HTTPException, status
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
import jwt
from jwt import PyJWTError
SECURITY_SCHEMES = {"jwt": {"type": "http", "scheme": "bearer"}}
security = HTTPBearer()
# Replace with your issuer and audience for strict validation
EXPECTED_ISSUER = "https://auth.example.com/"
ALLOWED_AUDIENCE = "api.example.com"
ALLOWED_HOSTS = {"api.example.com", "service-a.example.com"} # strict allowlist
def get_current_token(credentials: HTTPAuthorizationCredentials = Depends(security)) -> str:
return credentials.credentials
def decode_and_validate_token(token: str) -> dict:
try:
payload = jwt.decode(
token,
options={"verify_signature": True, "require": ["iss", "aud", "host"]},
issuer=EXPECTED_ISSUER,
audience=ALLOWED_AUDIENCE,
algorithms=["RS256"],
)
# Ensure the claim used for routing is within allowed hosts
host_claim = payload.get("host")
if not host_claim or host_claim not in ALLOWED_HOSTS:
raise ValueError("Invalid or missing host claim")
return payload
except PyJWTError as e:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail=f"Invalid token: {e}",
)
async def get_tenant_safe_host(payload: dict = Depends(decode_and_validate_token)) -> str:
# Return a pre-vetted host; do not construct URLs from raw token input
return payload["host"]
2. Use a strict allowlist for any URL/hostname construction
If you must derive a target host from a token claim, map it to a predefined configuration instead of using it directly in requests.
import httpx
from fastapi import APIRouter, Depends
router = APIRouter()
# Configuration mapping — not derived from token at runtime
TENANT_HOSTS = {
"tenant-a": "https://api-a.example.com",
"tenant-b": "https://api-b.example.com",
}
def get_tenant_config(tenant_id: str):
if tenant_id not in TENANT_HOSTS:
raise HTTPException(status_code=400, detail="Unknown tenant")
return TENANT_HOSTS[tenant_id]
@router.get("/proxy")
async def proxy_request(
tenant_id: str,
path: str,
config: str = Depends(get_tenant_config),
):
# Use a statically defined base URL; do not concatenate token-derived hostnames
url = f"{config.rstrip('/')}/{path.lstrip('/')}"
async with httpx.AsyncClient() as client:
resp = await client.get(url, timeout=5.0)
resp.raise_for_status()
return resp.json()
3. Avoid dynamic host resolution from tokens
Do not use JWT claims to form hostnames or perform DNS lookups. If you must store routing hints, store only safe identifiers and map them server-side to concrete, validated endpoints.
4. Enforce strict request timeouts and network policies
Even with validation, ensure outbound requests have timeouts and are restricted by network policies to prevent unintended reachability to dangling or unexpected hosts.
import httpx
# Example of safe outbound client with timeouts
client = httpx.AsyncClient(
timeout=httpx.Timeout(5.0, connect=2.0),
limits=httpx.Limits(max_connections=20),
)
These practices reduce the likelihood that a dangling DNS record can be leveraged via JWT manipulation. By strictly validating tokens, using allowlists, and avoiding runtime hostname construction from token claims, you align with secure API design principles and reduce risks such as BOLA/IDOR and SSRF that may involve dangling DNS references.