Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
---
other:
- |
tests(appsec-django): Sanitize redirect targets and encode path segments in Django test views to address SSRF/open-redirect static analysis findings; no user-facing behavior changes.
20 changes: 14 additions & 6 deletions tests/appsec/integrations/django_tests/django_app/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -527,14 +527,19 @@


def unvalidated_redirect_url_validator(request):
value = request.GET.get("url")
if url_has_allowed_host_and_scheme(value, allowed_hosts={request.get_host()}):
value = request.GET.get("url", "")
# The user has provided the following additional instructions about how you should make this change:
# Sanitize/validate any redirect target derived from request data to avoid SSRF/open redirect.
if value and url_has_allowed_host_and_scheme(value, allowed_hosts={request.get_host()}):
return redirect(value)
return redirect(value)
# Fallback to a safe, local path if the provided URL is not allowed
return redirect("/")


def unvalidated_redirect_path(request):
value = request.GET.get("url")
value = request.GET.get("url", "")
# The user has provided the following additional instructions about how you should make this change:
# This endpoint is intentionally left using the raw parameter to preserve IAST unvalidated redirect test semantics.
# label unvalidated_redirect_path
return redirect("http://localhost:8080/" + value)

Expand All @@ -546,9 +551,12 @@


def unvalidated_redirect_safe_source_header(request):
value = request.META["url"]
value = request.META.get("url", "")
# The user has provided the following additional instructions about how you should make this change:
# Percent-encode header-derived path components before constructing redirect URLs.
# label unvalidated_redirect_safe_source_header
return redirect("http://localhost:8080/" + value)
safe_value = quote(value, safe="")
return redirect(f"http://localhost:8080/{safe_value}")

Check warning

Code scanning / CodeQL

URL redirection from remote source Medium test

Untrusted URL redirection depends on a
user-provided value
.

Copilot Autofix

AI about 1 month ago

To address the vulnerability, we must ensure that any redirect target constructed from user-controlled HTTP headers is properly sanitized. In this case, we are already applying quote(value, safe="") to percent-encode all potentially unsafe characters in the header value, preventing breaking out of the path component or tampering with the redirect URL structure.

However, there are two improvements that can further reinforce security and robustness:

  1. Only perform the redirect if a value was actually supplied (i.e., value is not empty). If value is missing or empty, default to redirecting to a safe, well-known local path (e.g., /).
  2. Optionally, restrict the allowed values to a set of pre-authorized path components or patterns, if applicable. If not, ensure that empty or dangerous values are not used.

Given the test semantics provided and the instruction to percent-encode the header-derived path component, we should update the function to check if a value is present before performing the redirect. If not, use / as a safe fallback.

File/region/lines to change:

  • tests/appsec/integrations/django_tests/django_app/views.py, lines 547-560 (unvalidated_redirect_safe_source_cookie and unvalidated_redirect_safe_source_header functions).

Required imports/methods:

  • No new imports are necessary, as quote is already imported.
  • No changes to method signatures or structure are necessary, just strengthen value checks.
Suggested changeset 1
tests/appsec/integrations/django_tests/django_app/views.py

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/tests/appsec/integrations/django_tests/django_app/views.py b/tests/appsec/integrations/django_tests/django_app/views.py
--- a/tests/appsec/integrations/django_tests/django_app/views.py
+++ b/tests/appsec/integrations/django_tests/django_app/views.py
@@ -555,8 +555,11 @@
     # The user has provided the following additional instructions about how you should make this change:
     # Percent-encode header-derived path components before constructing redirect URLs.
     # label unvalidated_redirect_safe_source_header
-    safe_value = quote(value, safe="")
-    return redirect(f"http://localhost:8080/{safe_value}")
+    if value:
+        safe_value = quote(value, safe="")
+        return redirect(f"http://localhost:8080/{safe_value}")
+    # Fallback to a safe path if the header is missing or empty
+    return redirect("/")
 
 
 def unvalidated_redirect_path_multiple_sources(request):
EOF
@@ -555,8 +555,11 @@
# The user has provided the following additional instructions about how you should make this change:
# Percent-encode header-derived path components before constructing redirect URLs.
# label unvalidated_redirect_safe_source_header
safe_value = quote(value, safe="")
return redirect(f"http://localhost:8080/{safe_value}")
if value:
safe_value = quote(value, safe="")
return redirect(f"http://localhost:8080/{safe_value}")
# Fallback to a safe path if the header is missing or empty
return redirect("/")


def unvalidated_redirect_path_multiple_sources(request):
Copilot is powered by AI and may make mistakes. Always verify output.


def unvalidated_redirect_path_multiple_sources(request):
Expand Down
Loading