.agents/skills/sentry-backend-bugs/references/url-safety.md
15 issues, 126,318 events, 3,602 affected users. Redirect URLs that exceed safety limits, missing URL schemes in external URLs, and routing mismatches from URL construction.
Three sub-patterns:
https://), causing requests library to fail49,799 events | 897 users
In-app frames:
# sentry/middleware/access_log.py -- middleware()
# -> sentry/middleware/subdomain.py -- __call__()
# DisallowedRedirect: Unsafe redirect exceeding 2048 characters
Root cause: Users access Sentry URLs with very long query strings or path segments (often from malformed links, bots, or security scanners). The middleware chain attempts to redirect these requests (e.g., subdomain redirect, customer domain redirect, marketing landing redirect) but the resulting redirect URL exceeds the 2048-character safety limit. The DisallowedRedirect exception is thrown by Sentry's redirect safety middleware.
Fix:
def safe_redirect(url, max_length=2048):
if len(url) > max_length:
# Truncate to base URL without query string
parsed = urlparse(url)
base_url = f"{parsed.scheme}://{parsed.netloc}{parsed.path}"
if len(base_url) > max_length:
return HttpResponseBadRequest("URL too long")
return redirect(base_url)
return redirect(url)
Actual fix: Resolved -- all 8 DisallowedRedirect issues were fixed. The redirect paths now handle overly long URLs gracefully.
29,386 events | 81 users
In-app frames:
# sentry/middleware/customer_domain.py -- __call__()
# DisallowedRedirect: Unsafe redirect exceeding 2048 characters
Root cause: The customer domain middleware redirects requests from org.sentry.io paths to canonical URLs. When the original URL has a very long path or query string, the redirect URL exceeds 2048 characters.
Actual fix: Resolved -- middleware now validates redirect URL length.
13,965 events | 95 users (resolved)
# sentry/net/http.py
# MissingSchema: Invalid URL '': No scheme supplied. Perhaps you meant https://?
Root cause: An integration or webhook configuration stores an empty string as the target URL. When the code attempts to make an HTTP request to this URL, the requests library raises MissingSchema.
Fix:
if not url or not url.startswith(("http://", "https://")):
raise ValueError(f"Invalid URL: {url!r}")
1,280 events | 120 users
In-app frames:
# django/urls/resolvers.py
# NoReverseMatch: Reverse for 'sentry-api-0-organization-group-group-events' with
# keyword arguments {'organization_id_or_slug': '...', ...} not found
Root cause: URL construction uses reverse() with keyword arguments that do not match the URL pattern. This can happen when URL patterns are changed but callers are not updated, or when the URL parameter values contain characters that don't match the pattern regex.
Fix:
try:
url = reverse("sentry-api-0-organization-group-group-events", kwargs=kwargs)
except NoReverseMatch:
logger.warning("url.reverse_failed", extra={"url_name": url_name, "kwargs": kwargs})
url = None # Or construct manually
| Pattern | Frequency | Typical Trigger |
|---|---|---|
| Redirect URL too long | Very High | Bots, security scanners, malformed inbound links |
| Empty URL in integration config | High | Unconfigured or partially configured integrations |
| URL without scheme | Medium | User-provided URLs missing https:// prefix |
| NoReverseMatch from URL pattern changes | Low | URL refactoring without updating all callers |
def safe_redirect(request, url, max_length=2048):
if len(url) > max_length:
# Strip query string first
parsed = urlparse(url)
url = urlunparse(parsed._replace(query="", fragment=""))
if len(url) > max_length:
return HttpResponseBadRequest("URL too long")
return redirect(url)
def validate_url(url):
if not url:
raise ValueError("Empty URL")
if not url.startswith(("http://", "https://")):
raise ValueError(f"Missing URL scheme: {url!r}")
return url
try:
url = reverse(url_name, kwargs=kwargs)
except NoReverseMatch:
logger.warning("url.no_reverse_match", extra={"name": url_name})
url = fallback_url
def redirect_with_length_check(url):
if len(url) <= 2048:
return redirect(url)
# Try without query string
parsed = urlparse(url)
base = f"{parsed.scheme}://{parsed.netloc}{parsed.path}"
if len(base) <= 2048:
return redirect(base)
return HttpResponseBadRequest()
Scan the code for these patterns:
redirect() or HttpResponseRedirect() -- is the URL length validated?reverse() call -- is NoReverseMatch handled?