python.django.security.injection.open-redirect.open-redirect
semgrep
Author
6,332
Download Count*
License
Data from request ($DATA) is passed to redirect(). This is an open redirect and could be exploited. Ensure you are redirecting to safe URLs by using django.utils.http.is_safe_url(). See https://cwe.mitre.org/data/definitions/601.html for more information.
Run Locally
Run in CI
Defintion
rules:
- id: open-redirect
message: Data from request ($DATA) is passed to redirect(). This is an open
redirect and could be exploited. Ensure you are redirecting to safe URLs
by using django.utils.http.is_safe_url(). See
https://cwe.mitre.org/data/definitions/601.html for more information.
metadata:
cwe:
- "CWE-601: URL Redirection to Untrusted Site ('Open Redirect')"
owasp:
- A01:2021 - Broken Access Control
references:
- https://www.djm.org.uk/posts/djangos-little-protections-word-redirect-dangers/
- https://github.com/django/django/blob/d1b7bd030b1db111e1a3505b1fc029ab964382cc/django/utils/http.py#L231
category: security
technology:
- django
subcategory:
- vuln
likelihood: LOW
impact: MEDIUM
confidence: MEDIUM
license: Commons Clause License Condition v1.0[LGPL-2.1-only]
vulnerability_class:
- Open Redirect
languages:
- python
severity: WARNING
patterns:
- pattern-inside: |
def $FUNC(...):
...
- pattern-not-inside: |
def $FUNC(...):
...
django.utils.http.is_safe_url(...)
...
- pattern-not-inside: |
def $FUNC(...):
...
if <... django.utils.http.is_safe_url(...) ...>:
...
- pattern-not-inside: |
def $FUNC(...):
...
django.utils.http.url_has_allowed_host_and_scheme(...)
...
- pattern-not-inside: |
def $FUNC(...):
...
if <... django.utils.http.url_has_allowed_host_and_scheme(...) ...>:
...
- pattern-either:
- pattern: django.shortcuts.redirect(..., request.$W.get(...), ...)
- pattern: django.shortcuts.redirect(..., $S.format(..., request.$W.get(...),
...), ...)
- pattern: django.shortcuts.redirect(..., $S % request.$W.get(...), ...)
- pattern: django.shortcuts.redirect(..., f"...{request.$W.get(...)}...", ...)
- pattern: |
$DATA = request.$W.get(...)
...
django.shortcuts.redirect(..., $DATA, ...)
- pattern: |
$DATA = request.$W.get(...)
...
$INTERM = $DATA
...
django.shortcuts.redirect(..., $INTERM, ...)
- pattern: |
$DATA = request.$W.get(...)
...
django.shortcuts.redirect(..., $STR.format(..., $DATA, ...), ...)
- pattern: |
$DATA = request.$W.get(...)
...
$INTERM = $STR.format(..., $DATA, ...)
...
django.shortcuts.redirect(..., $INTERM, ...)
- pattern: |
$DATA = request.$W.get(...)
...
django.shortcuts.redirect(..., $STR % $DATA, ...)
- pattern: |
$DATA = request.$W.get(...)
...
$INTERM = $STR % $DATA
...
django.shortcuts.redirect(..., $INTERM, ...)
- pattern: |
$DATA = request.$W.get(...)
...
django.shortcuts.redirect(..., f"...{$DATA}...", ...)
- pattern: |
$DATA = request.$W.get(...)
...
$INTERM = f"...{$DATA}..."
...
django.shortcuts.redirect(..., $INTERM, ...)
- pattern: |
$DATA = request.$W.get(...)
...
django.shortcuts.redirect(..., $STR + $DATA, ...)
- pattern: |
$DATA = request.$W.get(...)
...
$INTERM = $STR + $DATA
...
django.shortcuts.redirect(..., $INTERM, ...)
- pattern: $A = django.shortcuts.redirect(..., request.$W.get(...), ...)
- pattern: $A = django.shortcuts.redirect(..., $S.format(..., request.$W.get(...),
...), ...)
- pattern: $A = django.shortcuts.redirect(..., $S % request.$W.get(...), ...)
- pattern: $A = django.shortcuts.redirect(..., f"...{request.$W.get(...)}...",
...)
- pattern: return django.shortcuts.redirect(..., request.$W.get(...), ...)
- pattern: return django.shortcuts.redirect(..., $S.format(...,
request.$W.get(...), ...), ...)
- pattern: return django.shortcuts.redirect(..., $S % request.$W.get(...), ...)
- pattern: return django.shortcuts.redirect(..., f"...{request.$W.get(...)}...",
...)
- pattern: django.shortcuts.redirect(..., request.$W(...), ...)
- pattern: django.shortcuts.redirect(..., $S.format(..., request.$W(...), ...),
...)
- pattern: django.shortcuts.redirect(..., $S % request.$W(...), ...)
- pattern: django.shortcuts.redirect(..., f"...{request.$W(...)}...", ...)
- pattern: |
$DATA = request.$W(...)
...
django.shortcuts.redirect(..., $DATA, ...)
- pattern: |
$DATA = request.$W(...)
...
$INTERM = $DATA
...
django.shortcuts.redirect(..., $INTERM, ...)
- pattern: |
$DATA = request.$W(...)
...
django.shortcuts.redirect(..., $STR.format(..., $DATA, ...), ...)
- pattern: |
$DATA = request.$W(...)
...
$INTERM = $STR.format(..., $DATA, ...)
...
django.shortcuts.redirect(..., $INTERM, ...)
- pattern: |
$DATA = request.$W(...)
...
django.shortcuts.redirect(..., $STR % $DATA, ...)
- pattern: |
$DATA = request.$W(...)
...
$INTERM = $STR % $DATA
...
django.shortcuts.redirect(..., $INTERM, ...)
- pattern: |
$DATA = request.$W(...)
...
django.shortcuts.redirect(..., f"...{$DATA}...", ...)
- pattern: |
$DATA = request.$W(...)
...
$INTERM = f"...{$DATA}..."
...
django.shortcuts.redirect(..., $INTERM, ...)
- pattern: |
$DATA = request.$W(...)
...
django.shortcuts.redirect(..., $STR + $DATA, ...)
- pattern: |
$DATA = request.$W(...)
...
$INTERM = $STR + $DATA
...
django.shortcuts.redirect(..., $INTERM, ...)
- pattern: $A = django.shortcuts.redirect(..., request.$W(...), ...)
- pattern: $A = django.shortcuts.redirect(..., $S.format(..., request.$W(...),
...), ...)
- pattern: $A = django.shortcuts.redirect(..., $S % request.$W(...), ...)
- pattern: $A = django.shortcuts.redirect(..., f"...{request.$W(...)}...", ...)
- pattern: return django.shortcuts.redirect(..., request.$W(...), ...)
- pattern: return django.shortcuts.redirect(..., $S.format(..., request.$W(...),
...), ...)
- pattern: return django.shortcuts.redirect(..., $S % request.$W(...), ...)
- pattern: return django.shortcuts.redirect(..., f"...{request.$W(...)}...", ...)
- pattern: django.shortcuts.redirect(..., request.$W[...], ...)
- pattern: django.shortcuts.redirect(..., $S.format(..., request.$W[...], ...),
...)
- pattern: django.shortcuts.redirect(..., $S % request.$W[...], ...)
- pattern: django.shortcuts.redirect(..., f"...{request.$W[...]}...", ...)
- pattern: |
$DATA = request.$W[...]
...
django.shortcuts.redirect(..., $DATA, ...)
- pattern: |
$DATA = request.$W[...]
...
$INTERM = $DATA
...
django.shortcuts.redirect(..., $INTERM, ...)
- pattern: |
$DATA = request.$W[...]
...
django.shortcuts.redirect(..., $STR.format(..., $DATA, ...), ...)
- pattern: |
$DATA = request.$W[...]
...
$INTERM = $STR.format(..., $DATA, ...)
...
django.shortcuts.redirect(..., $INTERM, ...)
- pattern: |
$DATA = request.$W[...]
...
django.shortcuts.redirect(..., $STR % $DATA, ...)
- pattern: |
$DATA = request.$W[...]
...
$INTERM = $STR % $DATA
...
django.shortcuts.redirect(..., $INTERM, ...)
- pattern: |
$DATA = request.$W[...]
...
django.shortcuts.redirect(..., f"...{$DATA}...", ...)
- pattern: |
$DATA = request.$W[...]
...
$INTERM = f"...{$DATA}..."
...
django.shortcuts.redirect(..., $INTERM, ...)
- pattern: |
$DATA = request.$W[...]
...
django.shortcuts.redirect(..., $STR + $DATA, ...)
- pattern: |
$DATA = request.$W[...]
...
$INTERM = $STR + $DATA
...
django.shortcuts.redirect(..., $INTERM, ...)
- pattern: $A = django.shortcuts.redirect(..., request.$W[...], ...)
- pattern: $A = django.shortcuts.redirect(..., $S.format(..., request.$W[...],
...), ...)
- pattern: $A = django.shortcuts.redirect(..., $S % request.$W[...], ...)
- pattern: $A = django.shortcuts.redirect(..., f"...{request.$W[...]}...", ...)
- pattern: return django.shortcuts.redirect(..., request.$W[...], ...)
- pattern: return django.shortcuts.redirect(..., $S.format(..., request.$W[...],
...), ...)
- pattern: return django.shortcuts.redirect(..., $S % request.$W[...], ...)
- pattern: return django.shortcuts.redirect(..., f"...{request.$W[...]}...", ...)
- pattern: django.shortcuts.redirect(..., request.$W, ...)
- pattern: django.shortcuts.redirect(..., $S.format(..., request.$W, ...), ...)
- pattern: django.shortcuts.redirect(..., $S % request.$W, ...)
- pattern: django.shortcuts.redirect(..., f"...{request.$W}...", ...)
- pattern: |
$DATA = request.$W
...
django.shortcuts.redirect(..., $DATA, ...)
- pattern: |
$DATA = request.$W
...
$INTERM = $DATA
...
django.shortcuts.redirect(..., $INTERM, ...)
- pattern: |
$DATA = request.$W
...
django.shortcuts.redirect(..., $STR.format(..., $DATA, ...), ...)
- pattern: |
$DATA = request.$W
...
$INTERM = $STR.format(..., $DATA, ...)
...
django.shortcuts.redirect(..., $INTERM, ...)
- pattern: |
$DATA = request.$W
...
django.shortcuts.redirect(..., $STR % $DATA, ...)
- pattern: |
$DATA = request.$W
...
$INTERM = $STR % $DATA
...
django.shortcuts.redirect(..., $INTERM, ...)
- pattern: |
$DATA = request.$W
...
django.shortcuts.redirect(..., f"...{$DATA}...", ...)
- pattern: |
$DATA = request.$W
...
$INTERM = f"...{$DATA}..."
...
django.shortcuts.redirect(..., $INTERM, ...)
- pattern: |
$DATA = request.$W
...
django.shortcuts.redirect(..., $STR + $DATA, ...)
- pattern: |
$DATA = request.$W
...
$INTERM = $STR + $DATA
...
django.shortcuts.redirect(..., $INTERM, ...)
- pattern: $A = django.shortcuts.redirect(..., request.$W, ...)
- pattern: $A = django.shortcuts.redirect(..., $S.format(..., request.$W, ...),
...)
- pattern: $A = django.shortcuts.redirect(..., $S % request.$W, ...)
- pattern: $A = django.shortcuts.redirect(..., f"...{request.$W}...", ...)
- pattern: return django.shortcuts.redirect(..., request.$W, ...)
- pattern: return django.shortcuts.redirect(..., $S.format(..., request.$W, ...),
...)
- pattern: return django.shortcuts.redirect(..., $S % request.$W, ...)
- pattern: return django.shortcuts.redirect(..., f"...{request.$W}...", ...)
- pattern: django.http.HttpResponseRedirect(..., request.$W.get(...), ...)
- pattern: django.http.HttpResponseRedirect(..., $S.format(...,
request.$W.get(...), ...), ...)
- pattern: django.http.HttpResponseRedirect(..., $S % request.$W.get(...), ...)
- pattern: django.http.HttpResponseRedirect(..., f"...{request.$W.get(...)}...",
...)
- pattern: |
$DATA = request.$W.get(...)
...
django.http.HttpResponseRedirect(..., $DATA, ...)
- pattern: |
$DATA = request.$W.get(...)
...
$INTERM = $DATA
...
django.http.HttpResponseRedirect(..., $INTERM, ...)
- pattern: >
$DATA = request.$W.get(...)
...
django.http.HttpResponseRedirect(..., $STR.format(..., $DATA, ...), ...)
- pattern: |
$DATA = request.$W.get(...)
...
$INTERM = $STR.format(..., $DATA, ...)
...
django.http.HttpResponseRedirect(..., $INTERM, ...)
- pattern: |
$DATA = request.$W.get(...)
...
django.http.HttpResponseRedirect(..., $STR % $DATA, ...)
- pattern: |
$DATA = request.$W.get(...)
...
$INTERM = $STR % $DATA
...
django.http.HttpResponseRedirect(..., $INTERM, ...)
- pattern: |
$DATA = request.$W.get(...)
...
django.http.HttpResponseRedirect(..., f"...{$DATA}...", ...)
- pattern: |
$DATA = request.$W.get(...)
...
$INTERM = f"...{$DATA}..."
...
django.http.HttpResponseRedirect(..., $INTERM, ...)
- pattern: |
$DATA = request.$W.get(...)
...
django.http.HttpResponseRedirect(..., $STR + $DATA, ...)
- pattern: |
$DATA = request.$W.get(...)
...
$INTERM = $STR + $DATA
...
django.http.HttpResponseRedirect(..., $INTERM, ...)
- pattern: $A = django.http.HttpResponseRedirect(..., request.$W.get(...), ...)
- pattern: $A = django.http.HttpResponseRedirect(..., $S.format(...,
request.$W.get(...), ...), ...)
- pattern: $A = django.http.HttpResponseRedirect(..., $S % request.$W.get(...),
...)
- pattern: $A = django.http.HttpResponseRedirect(...,
f"...{request.$W.get(...)}...", ...)
- pattern: return django.http.HttpResponseRedirect(..., request.$W.get(...), ...)
- pattern: return django.http.HttpResponseRedirect(..., $S.format(...,
request.$W.get(...), ...), ...)
- pattern: return django.http.HttpResponseRedirect(..., $S % request.$W.get(...),
...)
- pattern: return django.http.HttpResponseRedirect(...,
f"...{request.$W.get(...)}...", ...)
- pattern: django.http.HttpResponseRedirect(..., request.$W(...), ...)
- pattern: django.http.HttpResponseRedirect(..., $S.format(..., request.$W(...),
...), ...)
- pattern: django.http.HttpResponseRedirect(..., $S % request.$W(...), ...)
- pattern: django.http.HttpResponseRedirect(..., f"...{request.$W(...)}...", ...)
- pattern: |
$DATA = request.$W(...)
...
django.http.HttpResponseRedirect(..., $DATA, ...)
- pattern: |
$DATA = request.$W(...)
...
$INTERM = $DATA
...
django.http.HttpResponseRedirect(..., $INTERM, ...)
- pattern: >
$DATA = request.$W(...)
...
django.http.HttpResponseRedirect(..., $STR.format(..., $DATA, ...), ...)
- pattern: |
$DATA = request.$W(...)
...
$INTERM = $STR.format(..., $DATA, ...)
...
django.http.HttpResponseRedirect(..., $INTERM, ...)
- pattern: |
$DATA = request.$W(...)
...
django.http.HttpResponseRedirect(..., $STR % $DATA, ...)
- pattern: |
$DATA = request.$W(...)
...
$INTERM = $STR % $DATA
...
django.http.HttpResponseRedirect(..., $INTERM, ...)
- pattern: |
$DATA = request.$W(...)
...
django.http.HttpResponseRedirect(..., f"...{$DATA}...", ...)
- pattern: |
$DATA = request.$W(...)
...
$INTERM = f"...{$DATA}..."
...
django.http.HttpResponseRedirect(..., $INTERM, ...)
- pattern: |
$DATA = request.$W(...)
...
django.http.HttpResponseRedirect(..., $STR + $DATA, ...)
- pattern: |
$DATA = request.$W(...)
...
$INTERM = $STR + $DATA
...
django.http.HttpResponseRedirect(..., $INTERM, ...)
- pattern: $A = django.http.HttpResponseRedirect(..., request.$W(...), ...)
- pattern: $A = django.http.HttpResponseRedirect(..., $S.format(...,
request.$W(...), ...), ...)
- pattern: $A = django.http.HttpResponseRedirect(..., $S % request.$W(...), ...)
- pattern: $A = django.http.HttpResponseRedirect(..., f"...{request.$W(...)}...",
...)
- pattern: return django.http.HttpResponseRedirect(..., request.$W(...), ...)
- pattern: return django.http.HttpResponseRedirect(..., $S.format(...,
request.$W(...), ...), ...)
- pattern: return django.http.HttpResponseRedirect(..., $S % request.$W(...), ...)
- pattern: return django.http.HttpResponseRedirect(...,
f"...{request.$W(...)}...", ...)
- pattern: django.http.HttpResponseRedirect(..., request.$W[...], ...)
- pattern: django.http.HttpResponseRedirect(..., $S.format(..., request.$W[...],
...), ...)
- pattern: django.http.HttpResponseRedirect(..., $S % request.$W[...], ...)
- pattern: django.http.HttpResponseRedirect(..., f"...{request.$W[...]}...", ...)
- pattern: |
$DATA = request.$W[...]
...
django.http.HttpResponseRedirect(..., $DATA, ...)
- pattern: |
$DATA = request.$W[...]
...
$INTERM = $DATA
...
django.http.HttpResponseRedirect(..., $INTERM, ...)
- pattern: >
$DATA = request.$W[...]
...
django.http.HttpResponseRedirect(..., $STR.format(..., $DATA, ...), ...)
- pattern: |
$DATA = request.$W[...]
...
$INTERM = $STR.format(..., $DATA, ...)
...
django.http.HttpResponseRedirect(..., $INTERM, ...)
- pattern: |
$DATA = request.$W[...]
...
django.http.HttpResponseRedirect(..., $STR % $DATA, ...)
- pattern: |
$DATA = request.$W[...]
...
$INTERM = $STR % $DATA
...
django.http.HttpResponseRedirect(..., $INTERM, ...)
- pattern: |
$DATA = request.$W[...]
...
django.http.HttpResponseRedirect(..., f"...{$DATA}...", ...)
- pattern: |
$DATA = request.$W[...]
...
$INTERM = f"...{$DATA}..."
...
django.http.HttpResponseRedirect(..., $INTERM, ...)
- pattern: |
$DATA = request.$W[...]
...
django.http.HttpResponseRedirect(..., $STR + $DATA, ...)
- pattern: |
$DATA = request.$W[...]
...
$INTERM = $STR + $DATA
...
django.http.HttpResponseRedirect(..., $INTERM, ...)
- pattern: $A = django.http.HttpResponseRedirect(..., request.$W[...], ...)
- pattern: $A = django.http.HttpResponseRedirect(..., $S.format(...,
request.$W[...], ...), ...)
- pattern: $A = django.http.HttpResponseRedirect(..., $S % request.$W[...], ...)
- pattern: $A = django.http.HttpResponseRedirect(..., f"...{request.$W[...]}...",
...)
- pattern: return django.http.HttpResponseRedirect(..., request.$W[...], ...)
- pattern: return django.http.HttpResponseRedirect(..., $S.format(...,
request.$W[...], ...), ...)
- pattern: return django.http.HttpResponseRedirect(..., $S % request.$W[...], ...)
- pattern: return django.http.HttpResponseRedirect(...,
f"...{request.$W[...]}...", ...)
- pattern: django.http.HttpResponseRedirect(..., request.$W, ...)
- pattern: django.http.HttpResponseRedirect(..., $S.format(..., request.$W, ...),
...)
- pattern: django.http.HttpResponseRedirect(..., $S % request.$W, ...)
- pattern: django.http.HttpResponseRedirect(..., f"...{request.$W}...", ...)
- pattern: |
$DATA = request.$W
...
django.http.HttpResponseRedirect(..., $DATA, ...)
- pattern: |
$DATA = request.$W
...
$INTERM = $DATA
...
django.http.HttpResponseRedirect(..., $INTERM, ...)
- pattern: >
$DATA = request.$W
...
django.http.HttpResponseRedirect(..., $STR.format(..., $DATA, ...), ...)
- pattern: |
$DATA = request.$W
...
$INTERM = $STR.format(..., $DATA, ...)
...
django.http.HttpResponseRedirect(..., $INTERM, ...)
- pattern: |
$DATA = request.$W
...
django.http.HttpResponseRedirect(..., $STR % $DATA, ...)
- pattern: |
$DATA = request.$W
...
$INTERM = $STR % $DATA
...
django.http.HttpResponseRedirect(..., $INTERM, ...)
- pattern: |
$DATA = request.$W
...
django.http.HttpResponseRedirect(..., f"...{$DATA}...", ...)
- pattern: |
$DATA = request.$W
...
$INTERM = f"...{$DATA}..."
...
django.http.HttpResponseRedirect(..., $INTERM, ...)
- pattern: |
$DATA = request.$W
...
django.http.HttpResponseRedirect(..., $STR + $DATA, ...)
- pattern: |
$DATA = request.$W
...
$INTERM = $STR + $DATA
...
django.http.HttpResponseRedirect(..., $INTERM, ...)
- pattern: $A = django.http.HttpResponseRedirect(..., request.$W, ...)
- pattern: $A = django.http.HttpResponseRedirect(..., $S.format(..., request.$W,
...), ...)
- pattern: $A = django.http.HttpResponseRedirect(..., $S % request.$W, ...)
- pattern: $A = django.http.HttpResponseRedirect(..., f"...{request.$W}...", ...)
- pattern: return django.http.HttpResponseRedirect(..., request.$W, ...)
- pattern: return django.http.HttpResponseRedirect(..., $S.format(..., request.$W,
...), ...)
- pattern: return django.http.HttpResponseRedirect(..., $S % request.$W, ...)
- pattern: return django.http.HttpResponseRedirect(..., f"...{request.$W}...",
...)
- metavariable-regex:
metavariable: $W
regex: (?!get_full_path)
Examples
open-redirect.py
from django.shortcuts import redirect
from django.http import HttpResponseRedirect, HttpResponse
from django.utils.http import is_safe_url, url_has_allowed_host_and_scheme
def unsafe(request):
# ruleid: open-redirect
url = request.headers.get('referrer')
print("something")
return redirect(url)
def safe(request):
# ok: open-redirect
url = "https://lmnop.qrs"
return redirect(url)
def unsafe2(request):
# ruleid: open-redirect
url = request.POST.get("url")
return HttpResponseRedirect(url)
def unsafe3(request):
# ruleid: open-redirect
url = request.POST["url"]
return HttpResponseRedirect(url)
def unsafe4(request):
# ruleid: open-redirect
url = request.get_referrer() # I made this up, but if it exists don't do this
if url:
return HttpResponseRedirect(url)
def fine(request):
# ok: open-redirect
return HttpResponseRedirect(request.get_full_path())
def url_validation(request):
# ok: open-redirect
next = request.POST.get('next', request.GET.get('next'))
if (next or not request.is_ajax()) and not is_safe_url(url=next, allowed_hosts=request.get_host()):
next = "/index"
response = HttpResponseRedirect(next) if next else HttpResponse(status=204)
return response
def url_validation2(request):
# ok: open-redirect
next = request.POST.get('next', request.GET.get('next'))
ok = is_safe_url(url=next, allowed_hosts=request.get_host())
if ok:
response = HttpResponseRedirect(next) if next else HttpResponse(status=204)
else:
response = HttpResponseRedirect("index")
return response
def url_validation_django3(request):
# ok: open-redirect
next = request.POST.get('next', request.GET.get('next'))
if (next or not request.is_ajax()) and not url_has_allowed_host_and_scheme(url=next, allowed_hosts=request.get_host()):
next = "/index"
response = HttpResponseRedirect(next) if next else HttpResponse(status=204)
return response
def url_validation_django3_2(request):
# ok: open-redirect
next = request.POST.get('next', request.GET.get('next'))
ok = url_has_allowed_host_and_scheme(url=next, allowed_hosts=request.get_host())
if ok:
response = HttpResponseRedirect(next) if next else HttpResponse(status=204)
else:
response = HttpResponseRedirect("index")
return response
Short Link: https://sg.run/Ave2