Describe the bug
When a user denies an authorization request, the state parameter is concatenated directly into the redirect URL without URL-encoding.
In app/oauth/views/authorize.py (around line 157):
final_redirect_uri = f"{redirect_uri}?error=deny&state={state}"
return redirect(final_redirect_uri)
If an attacker-controlled state parameter contains special characters like &, =, or #, they will be interpreted as URL syntax rather than part of the state value. This can lead to HTTP Parameter Pollution (HPP) or fragment injection on the client's callback URL. Interestingly, the success path in the same file correctly uses encode_url() for parameters.
Expected behavior
The deny redirect should URL-encode the state parameter, consistent with the success path, to prevent query parameter injection:
from app.utils import encode_url
final_redirect_uri = f"{redirect_uri}?error=deny&state={encode_url(state)}"
Additional context
File: app/oauth/views/authorize.py line 157.
Describe the bug
When a user denies an authorization request, the
stateparameter is concatenated directly into the redirect URL without URL-encoding.In
app/oauth/views/authorize.py(around line 157):If an attacker-controlled state parameter contains special characters like &, =, or #, they will be interpreted as URL syntax rather than part of the state value. This can lead to HTTP Parameter Pollution (HPP) or fragment injection on the client's callback URL. Interestingly, the success path in the same file correctly uses encode_url() for parameters.
Expected behavior
The deny redirect should URL-encode the state parameter, consistent with the success path, to prevent query parameter injection:
Additional context
File: app/oauth/views/authorize.py line 157.