From cc14415eae6dade48a78d686782daaf2b6bcd70e Mon Sep 17 00:00:00 2001 From: xuans Date: Sat, 3 Oct 2026 14:38:08 +0800 Subject: [PATCH] =?UTF-8?q?=E6=94=B6=E7=B4=A7=E5=89=8D=E7=AB=AF=E9=9A=90?= =?UTF-8?q?=E8=97=8F=E8=B7=AF=E5=BE=84=E8=AE=BF=E9=97=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/internal/httpapi/frontend.go | 13 +++++++++++++ backend/internal/httpapi/frontend_test.go | 3 +++ 2 files changed, 16 insertions(+) diff --git a/backend/internal/httpapi/frontend.go b/backend/internal/httpapi/frontend.go index 8434e2b..ac8d2c0 100644 --- a/backend/internal/httpapi/frontend.go +++ b/backend/internal/httpapi/frontend.go @@ -33,6 +33,10 @@ func (s *Server) frontend(c *gin.Context) { c.Status(http.StatusNotFound) return } + if isHiddenFrontendPath(requestPath) { + c.Status(http.StatusNotFound) + return + } staticDir, err := filepath.Abs(s.frontendDir) if err != nil { @@ -81,6 +85,15 @@ func isCoreRequestPath(path string) bool { strings.HasPrefix(path, "/reset/") } +func isHiddenFrontendPath(path string) bool { + for _, segment := range strings.Split(strings.Trim(path, "/"), "/") { + if strings.HasPrefix(segment, ".") { + return true + } + } + return false +} + func isWithinDirectory(directory, candidate string) bool { relative, err := filepath.Rel(directory, candidate) if err != nil { diff --git a/backend/internal/httpapi/frontend_test.go b/backend/internal/httpapi/frontend_test.go index 58a025f..b16357a 100644 --- a/backend/internal/httpapi/frontend_test.go +++ b/backend/internal/httpapi/frontend_test.go @@ -36,6 +36,9 @@ func TestFrontendServesAssetsAndHistoryRoutes(t *testing.T) { {name: "root", method: http.MethodGet, path: "/", wantStatus: http.StatusOK, wantBody: "Scert"}, {name: "history route", method: http.MethodGet, path: "/login", wantStatus: http.StatusOK, wantBody: "Scert"}, {name: "asset", method: http.MethodGet, path: "/assets/app.js", wantStatus: http.StatusOK, wantBody: "console.log"}, + {name: "git metadata", method: http.MethodGet, path: "/.git/config", wantStatus: http.StatusNotFound}, + {name: "hidden file", method: http.MethodGet, path: "/.env", wantStatus: http.StatusNotFound}, + {name: "hidden asset", method: http.MethodGet, path: "/assets/.source-map", wantStatus: http.StatusNotFound}, {name: "missing asset", method: http.MethodGet, path: "/assets/missing.js", wantStatus: http.StatusNotFound}, {name: "unknown api", method: http.MethodGet, path: "/api/unknown", wantStatus: http.StatusNotFound}, {name: "post fallback", method: http.MethodPost, path: "/login", wantStatus: http.StatusNotFound},