Hallucination Attacks in Fastapi with Jwt Tokens
Hallucination Attacks in Fastapi with Jwt Tokens — how this specific combination creates or exposes the vulnerability
In Fastapi applications that rely on JWT tokens for authentication, hallucination attacks occur when an API returns fabricated or misleading data in response to manipulated or low-confidence inputs. This is not a parser or token handling issue directly; it is an authorization and input validation problem that becomes severe when access controls are misaligned with the data returned to the authenticated caller.
When JWT tokens are used, the identity and claims (such as scopes or roles) are typically trusted after signature verification. If the endpoint logic uses those claims to decide what data to return but does not enforce strict ownership or authorization checks (e.g., missing or incorrect BOLA/IDOR checks), an attacker with a valid JWT can request resources belonging to other users and receive responses that either do not match their permissions or hallucinate the existence of other resources. For example, an endpoint like /users/{user_id}/profile might verify the JWT and read the sub claim, but if the code ignores validating that the requested user_id matches the token claims, the API may hallucinate data by returning another user’s profile or indicating success when the resource does not exist for that user.
Additionally, hallucination can appear when an endpoint relies on incomplete query parameters or indirect object references while presenting a confident response. With JWT tokens, the API may assume that because authentication succeeded, the caller is authorized to query any identifier, leading to inconsistent states where the token claims are used to filter data at the application layer rather than enforcing data-level permissions at the database layer. This mismatch can expose sensitive data or allow an attacker to infer the existence of other users or resources, effectively hallucinating information that should remain hidden.
Proper defenses require that Fastapi endpoints validate not only the JWT signature but also enforce strict mapping between token claims and the requested resource identifiers. Each data access path must verify that the subject of the JWT owns or is explicitly authorized to view the target resource, using server-side checks and parameterized queries. Without this, even authenticated requests with valid JWT tokens can participate in hallucination attacks that leak information or misrepresent system state.
Jwt Tokens-Specific Remediation in Fastapi — concrete code fixes
To remediate hallucination risks when using JWT tokens in Fastapi, enforce strict authorization tied to token claims and validate all inputs before using them in database queries. Below are concrete, working examples that combine JWT verification with BOLA/IDOR-safe resource access patterns.
First, ensure JWT authentication is set up with proper token extraction and decoding, and that the decoded claims are used to enforce ownership on every request.
from fastapi import FastAPI, Depends, HTTPException, status
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
import jwt
from typing import Optional
app = FastAPI()
security = HTTPBearer()
SECRET_KEY = "your-secret-key"
ALGORITHM = "HS256"
def decode_jwt(token: str) -> dict:
try:
payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
return payload
except jwt.ExpiredSignatureError:
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Token expired")
except jwt.InvalidTokenError:
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Invalid token")
def get_current_subject(credentials: HTTPAuthorizationCredentials = Depends(security)) -> str:
payload = decode_jwt(credentials.credentials)
subject: Optional[str] = payload.get("sub")
if subject is None:
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Missing subject in token")
return subject
Next, create an authorization helper that validates that the requested resource belongs to the requesting subject. This prevents hallucination by ensuring the endpoint only returns data when the subject matches the resource identifier.
from fastapi import Depends
from pydantic import BaseModel
class Profile(BaseModel):
user_id: str
name: str
email: str
# Simulated database lookup function
def fetch_profile_from_db(user_id: str):
# In real code, this would be a database query parameterized by user_id
db = {
"alice": {"user_id": "alice", "name": "Alice", "email": "[email protected]"},
"bob": {"user_id": "bob", "name": "Bob", "email": "[email protected]"}
}
return db.get(user_id)
def get_profile_for_subject(requested_user_id: str, subject: str = Depends(get_current_subject)):
if requested_user_id != subject:
raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail="Forbidden: cannot access other user data")
profile = fetch_profile_from_db(requested_user_id)
if profile is None:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Profile not found")
return Profile(**profile)
Use the helper in your route so that every call validates both the JWT and the resource ownership, eliminating mismatched authorization that could lead to hallucination.
@app.get("/profiles/{user_id}", response_model=Profile)
def read_profile(user_id: str, profile: Profile = Depends(get_profile_for_subject)):
return profile
For list or search endpoints, apply server-side filtering on the server using the subject instead of trusting client-supplied filters that could hallucinate broader result sets.
from typing import List
class Item(BaseModel):
id: str
owner: str
name: str
def fetch_items_for_owner(owner: str):
# Simulated database items
all_items = [
{"id": "1", "owner": "alice", "name": "Item 1"},
{"id": "2", "owner": "alice", "name": "Item 2"},
{"id": "3", "owner": "bob", "name": "Item 3"}
]
return [Item(**item) for item in all_items if item["owner"] == owner]
@app.get("/items", response_model=List[Item])
def list_items(owner: str, subject: str = Depends(get_current_subject)):
if owner != subject:
raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail="Forbidden: cannot list other user items")
return fetch_items_for_owner(owner)
These patterns ensure that JWT tokens are used strictly for authentication while authorization checks are performed server-side, preventing attackers from hallucinating access to resources they do not own.
Related CWEs: llmSecurity
| CWE ID | Name | Severity |
|---|---|---|
| CWE-754 | Improper Check for Unusual or Exceptional Conditions | MEDIUM |