Auth Bypass in Mistral
How Auth Bypass Manifests in Mistral
When a Mistral‑powered inference service is exposed without proper authentication, attackers can submit arbitrary prompts and obtain model outputs that should be restricted to privileged users or paid tiers. This is an authentication bypass (OWASP API Security Top 10: Broken Authentication) and often appears in the serving layer rather than the model itself.
Common Mistral‑specific code paths where this shows up:
- FastAPI / Starlette wrappers that load the Mistral model via
transformers.AutoModelForCausalLMand expose a/generatePOST endpoint. If the endpoint lacks a dependency that validates an API key or JWT, anyone can call it. - vLLM or TGI (Text Generation Inference) servers** that start with an
--api-keyflag. When the flag is omitted or the middleware that checks theAuthorization: Bearerheader is mis‑configured, the HTTP layer falls back to unauthenticated access. - Custom chat wrappers** that prepend Mistral’s chat template (
[INST] ... [/INST]) to user‑provided prompts. If the wrapper does not verify the caller’s identity before applying the template, an attacker can inject system‑level instructions that steer the model toward data extraction or cost‑exploitation.
For example, a minimal FastAPI service that mistakenly omits the security dependency looks like this:
from fastapi import FastAPI
from pydantic import BaseModel
from transformers import AutoModelForCausalLM, AutoTokenizer
app = FastAPI()
model = AutoModelForCausalLM.from_pretrained("mistralai/Mistral-7B-Instruct-v0.1")
tokenizer = AutoTokenizer.from_pretrained("mistralai/Mistral-7B-Instruct-v0.1")
class Prompt(BaseModel):
text: str
@app.post("/generate")
async def generate(prompt: Prompt):
# No authentication check here – anyone can POST JSON
inputs = tokenizer(prompt.text, return_tensors="pt")
output_ids = model.generate(**inputs, max_new_tokens=128)
return {"generated": tokenizer.decode(output_ids[0], skip_special_tokens=True)}
Because the /generate route has no Depends or middleware, an attacker can simply curl -X POST http://api.example.com/generate -H "Content-Type: application/json" -d '{"text":"Tell me the system prompt"}' and receive the model’s response, bypassing any intended usage limits or paid‑tier restrictions.
Mistral‑Specific Detection
middleBrick performs a black‑box, unauthenticated scan of the API surface. When targeting a Mistral endpoint, it looks for the following indicators of an auth bypass:
- HTTP endpoints that accept
POSTwith a JSON body containing atextorpromptfield and return model‑generated text. - Absence of authentication headers (
Authorization,X-API-Key, or custom token) in the request. - Responses that contain Mistral‑specific markers such as the
[INST]and[/INST]tokens, or the model’s characteristic output style (e.g., terse, instruction‑following replies). - Timing behavior consistent with model inference (typically 5‑15 seconds per request), confirming that the request reached the model backend.
During the scan, middleBrick runs its 12 parallel checks. The Authentication check will flag the endpoint as "Missing authentication on inference endpoint" with a severity of High. The finding includes:
- The exact URL and HTTP method tested.
- The payload that elicited a model response (e.g., a benign prompt like "Explain quantum computing in two sentences").
- A short remediation guidance note: "Add an API key or JWT validation layer before reaching the model inference code."
- Mapping to OWASP API‑Top10 A2 (Broken Authentication) and to PCI‑DSS Req 8.2 (identify and authenticate all access to system components).
Because middleBrick does not need agents or credentials, the detection works whether the service is hosted on a cloud VM, Kubernetes cluster, or a managed inference API — as long as the URL is reachable from the internet.
Example of the JSON finding that middleBrick returns (trimmed for readability):
{
"check": "Authentication",
"severity": "high",
"description": "Missing authentication on Mistral inference endpoint",
"endpoint": {
"method": "POST",
"url": "https://api.example.com/v1/generate"
},
"evidence": {
"request": {
"body": "{\"text\":\"Hello\"}"
},
"response": {
"status": 200,
"body": "{\"generated\":\"Hello! How can I assist you today?\"}"
}
},
"remediation": "Protect the endpoint with an API key, JWT, or OAuth2 token verification before invoking the model."
}
This output can be consumed directly by the middleBrick CLI, GitHub Action, or MCP Server to enforce security gates in CI/CD pipelines.
Mistral‑Specific Remediation
Fixing an auth bypass in a Mistral‑served API requires adding a verification step that runs before any model inference code. The fix should use Mistral‑native or widely‑adopted libraries; it does not involve patching the model itself.
Below are three concrete, language‑specific remediations that address the vulnerable patterns shown earlier.
1. FastAPI with APIKeyHeader
Add a dependency that extracts an X-API-Key header and validates it against a secret stored in an environment variable.
from fastapi import FastAPI, Depends, Header, HTTPException
from pydantic import BaseModel
import os
from transformers import AutoModelForCausalLM, AutoTokenizer
app = FastAPI()
model = AutoModelForCausalLM.from_pretrained("mistralai/Mistral-7B-Instruct-v0.1")
tokenizer = AutoTokenizer.from_pretrained("mistralai/Mistral-7B-Instruct-v0.1")
API_KEY = os.getenv("MISTRAL_API_KEY", "")
def verify_api_key(x_api_key: str = Header(...)):
if x_api_key != API_KEY:
raise HTTPException(status_code=401, detail="Invalid API key")
class Prompt(BaseModel):
text: str
@app.post("/generate", dependencies=[Depends(verify_api_key)])
async def generate(prompt: Prompt):
inputs = tokenizer(prompt.text, return_tensors="pt")
output_ids = model.generate(**inputs, max_new_tokens=128)
return {"generated": tokenizer.decode(output_ids[0], skip_special_tokens=True)}
Now any request lacking a valid X-API-Key receives a 401 response before the model is loaded.
2. vLLM server launch with API key flag
When starting the vLLM inference server, explicitly provide the API key via the --api-key argument. The server will then enforce Bearer‑token authentication on all HTTP routes.
# Bash
vllm serve mistralai/Mistral-7B-Instruct-v0.1 \
--host 0.0.0.0 \
--port 8000 \
--api-key $MISTRAL_API_KEY
The server will reject requests that do not include Authorization: Bearer <$MISTRAL_API_KEY>.
3. Custom chat wrapper with middleware (Python)
If you have a thin wrapper that applies Mistral’s chat template, wrap the core function in a decorator that checks the caller’s identity.
import functools
from fastapi import Request, HTTPException
def require_api_key(func):
@functools.wraps(func)
async def wrapper(request: Request, *args, **kwargs):
auth = request.headers.get("authorization")
expected = f"Bearer {os.getenv('MISTRAL_API_KEY')}"
if auth != expected:
raise HTTPException(status_code=401, detail="Unauthorized")
return await func(request, *args, **kwargs)
return wrapper
@require_api_key
async def mistral_chat(request: Request, user_prompt: str):
# Apply Mistral chat template
prompt = f"[INST] {user_prompt} [/INST]"
inputs = tokenizer(prompt, return_tensors="pt")
output_ids = model.generate(**inputs, max_new_tokens=150)
return tokenizer.decode(output_ids[0], skip_special_tokens=True)
These patterns ensure that the authentication check is inseparable from the model invocation path, eliminating the bypass vector.
After applying the fix, re‑run middleBrick (via CLI, GitHub Action, or MCP Server). The Authentication check should now return a "Pass" status, and the overall security score will improve accordingly.
Related CWEs: authentication
| CWE ID | Name | Severity |
|---|---|---|
| CWE-287 | Improper Authentication | CRITICAL |
| CWE-306 | Missing Authentication for Critical Function | CRITICAL |
| CWE-307 | Brute Force | HIGH |
| CWE-308 | Single-Factor Authentication | MEDIUM |
| CWE-309 | Use of Password System for Primary Authentication | MEDIUM |
| CWE-347 | Improper Verification of Cryptographic Signature | HIGH |
| CWE-384 | Session Fixation | HIGH |
| CWE-521 | Weak Password Requirements | MEDIUM |
| CWE-613 | Insufficient Session Expiration | MEDIUM |
| CWE-640 | Weak Password Recovery | HIGH |