From c7440c2c3366e516ef9b0f4c34093e0c7f5c23d4 Mon Sep 17 00:00:00 2001 From: Runxi Yu Date: Sat, 22 Mar 2025 11:44:59 +0800 Subject: [PATCH] Fix tree/raw redirection and disallow slashes in their path segments --- http_error_page.go | 6 ++++++ http_handle_repo_raw.go | 7 ++----- http_handle_repo_tree.go | 3 +-- http_server.go | 9 ++++++++- templates/400.tmpl | 25 +++++++++++++++++++++++++ url.go | 9 +++++++++ diff --git a/http_error_page.go b/http_error_page.go index aabc9bd5c90bfc86923eca0baa6bb561e7dcf9d1..39807974aced11f322cf1e7138c7ead681cc700e 100644 --- a/http_error_page.go +++ b/http_error_page.go @@ -11,3 +11,9 @@ func errorPage404(w http.ResponseWriter, params map[string]any) { w.WriteHeader(404) _ = templates.ExecuteTemplate(w, "404", params) } + +func errorPage400(w http.ResponseWriter, params map[string]any, msg string) { + w.WriteHeader(400) + params["bad_request_msg"] = msg + _ = templates.ExecuteTemplate(w, "400", params) +} diff --git a/http_handle_repo_raw.go b/http_handle_repo_raw.go index e39885681324d5500452485441b3ad2788ccd865..8664ceb9500b71b65c8682c2af1e237b4a08f140 100644 --- a/http_handle_repo_raw.go +++ b/http_handle_repo_raw.go @@ -6,7 +6,6 @@ import ( "fmt" "net/http" - "path" "strings" "github.com/go-git/go-git/v5" @@ -51,8 +50,7 @@ if file, err = tree.File(pathSpec); err != nil { http.Error(w, "Error retrieving path: "+err.Error(), http.StatusInternalServerError) return } - if len(rawPathSpec) != 0 && rawPathSpec[len(rawPathSpec)-1] == '/' { - http.Redirect(w, r, "../"+pathSpec, http.StatusSeeOther) + if redirectNoDir(w, r) { return } if fileContent, err = file.Contents(); err != nil { @@ -64,8 +62,7 @@ return } } - if len(rawPathSpec) != 0 && rawPathSpec[len(rawPathSpec)-1] != '/' { - http.Redirect(w, r, path.Base(pathSpec)+"/", http.StatusSeeOther) + if redirectDir(w, r) { return } diff --git a/http_handle_repo_tree.go b/http_handle_repo_tree.go index a1a3ca4d9d536ef55c9235765b971d4dc0d9396b..36eefc03c261bdc7a0721fba9d17e98183f2d029 100644 --- a/http_handle_repo_tree.go +++ b/http_handle_repo_tree.go @@ -61,8 +61,7 @@ if file, err = tree.File(pathSpec); err != nil { http.Error(w, "Error retrieving path: "+err.Error(), http.StatusInternalServerError) return } - if len(rawPathSpec) != 0 && rawPathSpec[len(rawPathSpec)-1] == '/' { - http.Redirect(w, r, "../"+pathSpec, http.StatusSeeOther) + if redirectNoDir(w, r) { return } if fileContent, err = file.Contents(); err != nil { diff --git a/http_server.go b/http_server.go index c883cdf07f6d3ad813b78c8b4de8e1c57f48fc43..584c48dec9f5525f3f46853651a11e411e205ea0 100644 --- a/http_server.go +++ b/http_server.go @@ -28,7 +28,6 @@ http.Error(w, err.Error(), http.StatusBadRequest) return } if segments[len(segments)-1] == "" { - // Might assign a trailing bool here segments = segments[:len(segments)-1] } @@ -172,12 +171,20 @@ repoFeature := segments[sepIndex+3] switch repoFeature { case "tree": + if anyContain(segments[sepIndex+4:], "/") { + errorPage400(w, params, "Repo tree paths may not contain slashes in any segments") + return + } params["rest"] = strings.Join(segments[sepIndex+4:], "/") if len(segments) < sepIndex+5 && redirectDir(w, r) { return } httpHandleRepoTree(w, r, params) case "raw": + if anyContain(segments[sepIndex+4:], "/") { + errorPage400(w, params, "Repo tree paths may not contain slashes in any segments") + return + } params["rest"] = strings.Join(segments[sepIndex+4:], "/") if len(segments) < sepIndex+5 && redirectDir(w, r) { return diff --git a/templates/400.tmpl b/templates/400.tmpl new file mode 100644 index 0000000000000000000000000000000000000000..1fcd5d919d72c25f81e876b68567798f36f8a172 --- /dev/null +++ b/templates/400.tmpl @@ -0,0 +1,25 @@ +{{/* + SPDX-License-Identifier: AGPL-3.0-only + SPDX-FileContributor: Runxi Yu +*/}} +{{- define "400" -}} + + + + {{- template "head_common" . -}} + 400 Bad Request – {{ .global.forge_title }} + + + {{- template "header" . -}} +
+

400 Bad Request

+

{{- .bad_request_msg -}}

+
+
Lindenii Forge
+
+ + + +{{- end -}} diff --git a/url.go b/url.go index 3978c6e6ab3135b97fe34d39874ad7613cf4a007..57cb196bc554af149c11b668baf2f4fa4ac580d3 100644 --- a/url.go +++ b/url.go @@ -119,3 +119,12 @@ segments[i] = url.PathEscape(segment) } return strings.Join(segments, "/") } + +func anyContain(ss []string, c string) bool { + for _, s := range ss { + if strings.Contains(s, c) { + return true + } + } + return false +} -- 2.48.1