Reject leading backslash in post-login redirect target - #7777
Conversation
_is_safe_next_url() normalizes backslash to slash before validating, so "\evil.com" becomes "/evil.com" and passes as a safe relative path. The test_backslash_redirect_rejected test (added in 9e66f81) expects it to be rejected, so master's backend unit tests have failed since that commit. Reject any target that starts with a backslash. A valid on-site path never starts with one. This also covers \\evil.com and \/evil.com, which browsers read as //evil.com. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Greptile SummaryThis PR fixes an open-redirect bypass in
Confidence Score: 5/5Safe to merge — the change is a minimal, targeted guard that closes a confirmed open-redirect bypass without affecting any legitimate redirect paths. The fix is a single early-return check added before the existing normalization loop. The logic is correct: valid on-site paths never start with a backslash, so the guard cannot block legitimate redirects. The previously failing test test_backslash_redirect_rejected now passes, and get_next_path already falls back to './' for any input that fails _is_safe_next_url and has no netloc, so the end-to-end behavior is sound. Files Needing Attention: No files require special attention.
|
| Filename | Overview |
|---|---|
| redash/authentication/init.py | Adds a leading-backslash early-reject guard to _is_safe_next_url, correctly fixing an open-redirect bypass where \evil.com normalized through the existing replace loop to /evil.com and passed validation. |
Flowchart
%%{init: {'theme': 'neutral'}}%%
flowchart TD
A["next= URL from query string"] --> B{"Empty or blank?"}
B -- Yes --> Z["Return './'"]
B -- No --> C{"Leading control char?"}
C -- Yes --> Z
C -- No --> D{"Starts with backslash?\n(NEW GUARD)"}
D -- Yes --> Z
D -- No --> E{"Check original URL\n& backslash-normalized URL"}
E -- "Has netloc / bad scheme / starts with ///" --> Z
E -- Clean --> F["_is_safe_next_url → True"]
F --> G["Return URL as-is"]
F --> H{"URL not safe?\nget_next_path fallback"}
H -- "No netloc in urlsplit" --> Z
H -- "Has netloc + http(s)" --> I["Extract path component only"]
I --> G
Reviews (1): Last reviewed commit: "Reject leading backslash in post-login r..." | Re-trigger Greptile
|
dup #7774 |
Problem
_is_safe_next_url()treats\evil.comas a safe post-login redirect target. It normalizes backslash to slash before validating, so\evil.combecomes/evil.comand passes as a relative path.test_backslash_redirect_rejected(added in 9e66f81) expects\evil.comto be rejected. As a result, master'sbackend-unit-testshave been failing since that commit.Fix
Reject any redirect target that starts with a backslash. A valid on-site path always starts with a forward slash or a path segment, never a backslash, so this does not affect legitimate redirects. It also covers
\\evil.comand\/evil.com, which browsers read as//evil.com.Test
All redirect cases in
TestRedirectToUrlAfterLoggingInpass, including the previously failing\evil.com, with no change to valid paths such as//localhost/queries->/queries.