Configuration & Environment
MCP server decodes JWTs with `verify=False`, `algorithms: ["none"]`, or bare `jwt.decode()` from the JS jsonwebtoken package — accepting unsigned tokens that any client can forge.
JWT signature verification is the only thing standing between attacker-controlled token claims and the application trusting them. Disabling it (Python `verify=False`, JS `algorithms: ["none"]`, or PyJWT's `options={"verify_signature": False}`) means base64-decoded attacker input becomes a trusted identity.
MCP servers that use OAuth or session-style JWTs as their auth primitive are common. The disabled-verify pattern most often shows up when a developer was debugging signature errors and forgot to re-enable verification, or copied a snippet from a tutorial that said "in development mode..." The bug ships to production silently.
import jwt |
def authenticate(token: str) -> dict: |
# No signature verification. |
return jwt.decode(token, options={"verify_signature": False}) |
import jwt |
JWT_KEY = os.environ["JWT_PUBLIC_KEY"] |
def authenticate(token: str) -> dict: |
return jwt.decode(token, JWT_KEY, algorithms=["RS256"], audience="my-mcp-server") |
MCPSafe matches three sub-patterns: (1) JS `jwt.verify(token, key, { algorithms: ["none"] })`; (2) Python PyJWT `jwt.decode(..., verify=False)` or `options={"verify_signature": False}`; (3) JS `jwt.decode(token)` (which doesn't validate signature) in a file that imports `jsonwebtoken` and never calls `jwt.verify`.
See the full threat catalog for every documented detection.
MCPSafe runs this check — and every other rule in the catalog — on any MCP server you paste in.
Scan now