Prevent redirect bypasses via backslash-encoded paths#36660
Prevent redirect bypasses via backslash-encoded paths#36660silverwind merged 10 commits intogo-gitea:mainfrom
Conversation
modules/httplib/url.go
Outdated
| return false | ||
| } | ||
| // Backslashes (including encoded) can be normalized by browsers into slashes and allow open redirects. | ||
| if strings.Contains(s, "\\") || strings.Contains(strings.ToLower(s), "%5c") { |
There was a problem hiding this comment.
Hmm yeah the comment and code contradict. If browser normalizes to /, the characters will appear as / here. More context is needed to truly understand the issue.
There was a problem hiding this comment.
I have updated the PR content to have a description and reproducible address.
|
Review by @silverwind, written with Claude Code. Looks correct. The fix addresses open redirect via backslash normalization: browsers can normalize With the new blanket backslash check, the backslash cases in the old prefix check on line 24 ( if len(s) >= 2 && s[0] == '/' && s[1] == '/' {
return false
}Other observations:
The PR description is empty — it would be good to mention this is a security fix for open redirect via backslash normalization, for changelog/backport purposes. |
I'm sorry but such reviews are unactionable. You need to at least give some hint what you feel is wrong. |
I can only see you copy-paste the AI response. Since you have approved, can you answer the questions?
|
|
@silverwind @lunny , you see, even if I explained, there is no progress. Why should I waste time on explaining? That's why I only say "wrong" to the people who don't understand the problem and never learn from lessons. |
|
I would help if the PR description contains some actual reasoning for the change or a link to the security report it relates to. |
|
I will continue the work. Thank you for the review. |
This one will not, I removed it from test.
%5c will be decoded to \ and the whole string will be considered as
I think it might that Web browsers thinks
The code will be used on |
|
Still, completely wrong. If 1 doesn't, why 2 does? Are you able to reproduce in 3 Have you read code for 4? What if The logic itself is wrong. Really curious that whether you use your brain when you write code. |
@silverwind @lunny the questions are still not addressed |
Check u.Path (parsed, decoded path component) for backslashes instead of checking the raw string for literal backslashes or %5c. This avoids false positives on query parameters while correctly catching path traversal attacks like "/a/../\example.com" that browsers can normalize to "//example.com" (protocol-relative open redirect). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
Written by @silverwind using Claude Code. I pushed a reworked fix to the branch that addresses wxiaoguang's feedback. The key issues with the previous approach:
The new approach: Check
Test cases include both exploit vectors ( |
|
Proper fix applied and added test cases so this does not reject valid backslashes in query. |
There is a slight difference in the implementations in golang, but practically not meaningful.
More test cases are always valuable imho so you can be sure the implemenation catches all edge cases. |
Show me, what edge cases. Don't just guess. |
|
Your tests validate the same as mine. That's fine but you could have just mentioned that and we save this whole discussion. |
But why you don't read code but only guess? |
|
I saw you reverting my stuff and then I compared the tests only in a fleeting fashion. |
This change tightens relative URL validation to reject raw backslashes and `%5c` (encoded backslash), since browsers and URL normalizers can treat backslashes as path separators. That normalization can turn seemingly relative paths into scheme-relative URLs, creating open-redirect risk. Visiting below URL to reproduce the problem. http://localhost:3000/user/login?redirect_to=/a/../\example.com http://localhost:3000/user/login?redirect_to=/a/../%5cexample.com --------- Co-authored-by: silverwind <me@silverwind.io> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
Backport #36660 by @lunny This change tightens relative URL validation to reject raw backslashes and `%5c` (encoded backslash), since browsers and URL normalizers can treat backslashes as path separators. That normalization can turn seemingly relative paths into scheme-relative URLs, creating open-redirect risk. Visiting below URL to reproduce the problem. http://localhost:3000/user/login?redirect_to=/a/../\example.com http://localhost:3000/user/login?redirect_to=/a/../%5cexample.com Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com> Co-authored-by: silverwind <me@silverwind.io> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
* giteaofficial/main: (81 commits) Add keyboard shortcuts for repository file and code search (go-gitea#36416) Refactor text utility classes to Tailwind CSS (go-gitea#36703) Prevent redirect bypasses via backslash-encoded paths (go-gitea#36660) Fix force push time-line commit comments of pull request (go-gitea#36653) Fix get release draft permission check (go-gitea#36659) Move `X_FRAME_OPTIONS` setting from `cors` to `security` section (go-gitea#30256) Update JS and PY deps (go-gitea#36708) Move jobparser from act repository to Gitea (go-gitea#36699) Fix push time bug (go-gitea#36693) Add icon to buttons "Close with Comment", "Close Pull Request", "Close Issue" (go-gitea#36654) various fixes (go-gitea#36697) Add AI Contribution Policy to CONTRIBUTING.md (go-gitea#36651) Add some validation on values provided to USER_DISABLED_FEATURES and EXTERNAL_USER_DISABLED_FEATURES (go-gitea#36688) Rework e2e tests (go-gitea#36634) Remove unused functions (go-gitea#36672) Add migration http transport for push/sync mirror lfs (go-gitea#36665) Fix track time issue id (go-gitea#36664) Refactor inline style attributes (go-gitea#36652) Update Nix flake (go-gitea#36679) Upgrade gogit to 5.16.5 (go-gitea#36680) ... # Conflicts: # web_src/js/features/repo-issue-content.ts
|
As I see it, it's the job of the PR author or whoever pushes commits to keep the OP message correct, I always do that for my PRs. |
* main: (24 commits) Instance-wide (global) info banner and maintenance mode (go-gitea#36571) Add created_by filter to SearchIssues (go-gitea#36670) Inline and lazy-load EasyMDE CSS, fix border colors (go-gitea#36714) Fix release draft access check logic (go-gitea#36720) Change image transparency grid to CSS (go-gitea#36711) Avoid opening new tab when downloading actions logs (go-gitea#36740) Add validation constraints for repository creation fields (go-gitea#36671) Fix SVG height calculation in diff viewer (go-gitea#36748) Fix path resolving (go-gitea#36734) [skip ci] Updated translations via Crowdin Fix track time list permission check (go-gitea#36662) Fix incorrect setting loading order (go-gitea#36735) Use case-insensitive matching for Git error "Not a valid object name" (go-gitea#36728) feat: Add workflow dependencies visualization (go-gitea#36248) Add keyboard shortcuts for repository file and code search (go-gitea#36416) Refactor text utility classes to Tailwind CSS (go-gitea#36703) Prevent redirect bypasses via backslash-encoded paths (go-gitea#36660) Fix force push time-line commit comments of pull request (go-gitea#36653) Fix get release draft permission check (go-gitea#36659) Move `X_FRAME_OPTIONS` setting from `cors` to `security` section (go-gitea#30256) ... # Conflicts: # web_src/css/base.css # web_src/css/index.css

This change tightens relative URL validation to reject raw backslashes and
%5c(encoded backslash), since browsers and URL normalizers can treat backslashes as path separators. That normalization can turn seemingly relative paths into scheme-relative URLs, creating open-redirect risk.Visiting below URL to reproduce the problem.
http://localhost:3000/user/login?redirect_to=/a/../\example.com
http://localhost:3000/user/login?redirect_to=/a/../%5cexample.com