Interactive Playground
Experiment with the vulnerable code and security rule below. Edit the code to see how the rule detects different vulnerability patterns.
pathfinder scan --ruleset python/PYTHON-JWT-SEC-005 --project .About This Rule
Understanding the vulnerability and how it is detected
This rule uses taint analysis to trace user-controlled data from web framework request objects into jwt.encode() calls. When user input flows directly into a JWT payload without validation, two things can go wrong: the user might submit sensitive data (passwords, personal information) that ends up base64-encoded in a readable token, or an attacker might inject claims that affect authorization decisions.
Unlike the other JWT rules that use pattern matching, this rule tracks actual data flow. It starts from Flask request methods (request.args.get, request.form.get) and Django request methods (request.GET.get, request.POST.get), follows the data through variable assignments, and flags when it reaches jwt.encode(). It uses standard propagation presets to track how data moves through the code.
This is the most precise JWT rule in the set -- it only fires when there's a proven data flow from user input to token creation. No data flow, no finding.
Security Implications
Potential attack scenarios if this vulnerability is exploited
Sensitive Data Exposure via Token
If a user submits their password, SSN, or credit card number through a form, and that data flows into jwt.encode(), it ends up in a JWT that's visible to anyone who intercepts it. JWTs are not encrypted -- the payload is just base64-encoded JSON.
Claim Injection
If user input becomes a JWT claim without validation, an attacker could inject authorization-relevant claims. For example, if the "role" field comes from user input, the attacker can set it to "admin". The token will be validly signed because the server created it, but with attacker-controlled claims.
Token Size Attacks
Unsanitized user input in JWT payloads can make tokens arbitrarily large. Large tokens can cause issues with cookie size limits (4KB), header size limits in proxies and load balancers, and increased bandwidth usage.
How to Fix
Recommended remediation steps
- 1Never pass raw user input directly into jwt.encode() -- validate it against your database or business logic first
- 2Build JWT payloads from server-side data, not from request parameters -- look up the user by their input, then use the server's record of their ID and role
- 3Whitelist which fields can appear in the JWT payload and reject anything else
- 4Validate input types and lengths before including them in any token
- 5Consider whether the data needs to be in the token at all -- can the consuming service look it up by user_id instead?
Detection Scope
How Code Pathfinder analyzes your code for this vulnerability
This rule uses intra-procedural taint analysis (scope=local) to trace data from Flask request methods (request.args.get, request.form.get, request.GET.get, request.POST.get) to jwt.encode() as a sink. It uses standard propagation presets to track how tainted data flows through variable assignments. The flow must be within a single function -- cross-function flows require scope=global.
Compliance & Standards
Industry frameworks and regulations that require detection of this vulnerability
References
External resources and documentation
Similar Rules
Explore related security rules for Python
JWT Exposed Credentials
Detects jwt.encode() calls where passwords or secrets may be included in the token payload, exposing them to anyone who reads the token.
Flask SQL Injection via Tainted String
Finds user input reaching raw SQL queries in Flask apps where parameterized queries should be used instead.
Django SQL Injection via cursor.execute()
User input flows to cursor.execute() without parameterization, enabling SQL injection attacks.
Frequently Asked Questions
Common questions about JWT User Input in Payload
New feature
Get these findings posted directly on your GitHub pull requests
The JWT User Input in Payload rule runs in CI and posts inline review comments on the exact lines — no dashboard, no SARIF viewer.