Block open redirect via backslash in redirect Location#2729
Open
ATOM00blue wants to merge 1 commit into
Open
Conversation
The leading-slash collapse added for simonw#2429 only stripped forward slashes, so a path like /\example.com/ (or its %5C-encoded form) was redirected to Location: /\example.com. Browsers treat a backslash as a slash, so that resolves to //example.com and then https://example.com, re-opening the open redirect. Collapse leading backslashes as well as slashes. Extends the existing slash-slash test to cover /\example.com/ and /\/example.com/. Fixes simonw#2680
There was a problem hiding this comment.
Pull request overview
Addresses a regression in Datasette’s open-redirect protection by ensuring redirect Location headers can’t be made protocol-relative via leading backslashes (which browsers treat like forward slashes).
Changes:
- Harden
asgi_send_redirect()to collapse leading backslashes as well as forward slashes (^[/\\]+). - Expand and rename the existing custom-pages redirect regression test to cover backslash-based variants of the attack.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| datasette/utils/asgi.py | Updates redirect sanitization to treat leading backslashes like leading slashes to prevent protocol-relative redirects. |
| tests/test_custom_pages.py | Extends the redirect regression test to cover //example.com/, /\\example.com/, and /\\/example.com/ cases. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| def test_custom_route_pattern_open_redirect_302(custom_pages_client, path): | ||
| response = custom_pages_client.get(path) | ||
| assert response.status == 302 | ||
| assert response.headers["location"] == "/example.com" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #2680
The bug
The open-redirect protection added for #2429 collapses leading slashes in the redirect
Locationheader so that//example.com/becomes/example.com. It only strips forward slashes though:A request to
/\example.com/(or its%5C-encoded form, which proxies/servers may decode to a literal backslash before it reaches Datasette) therefore redirects toLocation: /\example.com. Browsers treat a backslash the same as a forward slash, so the browser reads that as//example.comand follows it tohttps://example.com— the open redirect is back./\/example.com/works the same way.Reproduction
Against
main:The fix
Collapse leading backslashes as well as slashes in
asgi_send_redirect:Now all three cases redirect to the same-origin path
/example.com. Inner slashes/backslashes are left untouched, so normal paths are unaffected.Testing
Extended the existing
//example.com/test (renamed totest_custom_route_pattern_open_redirect_302) to cover/\example.com/and/\/example.com/. The two new cases fail before this change and pass after.pytest tests/test_custom_pages.pyand the redirect/404 tests across the suite are green, andblackreports no changes.