From b763d787d1f2b862c577049e4ee147c5857fe413 Mon Sep 17 00:00:00 2001 From: Qiaochu Hu <110hqc@gmail.com> Date: Sun, 10 May 2026 19:01:32 +0800 Subject: [PATCH] :lock: Fix path traversal vulnerability in /export/temp/ endpoint (#17656) The /export/temp/ endpoint used c.Request.URL.Path directly in filepath.Join without any validation, allowing path traversal via sequences like /export/temp/../../ to access files outside the intended temp directory. This fix: - Constrains file access to {TempDir}/export/temp/ base directory - Cleans the relative path with filepath.Clean - Rejects paths containing ".." - Validates the final path with IsSubPath check Co-authored-by: Test User Co-authored-by: Claude Opus 4.7 --- kernel/server/serve.go | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/kernel/server/serve.go b/kernel/server/serve.go index 5ed8dc6d8..477110d6a 100644 --- a/kernel/server/serve.go +++ b/kernel/server/serve.go @@ -304,10 +304,21 @@ func serveExport(ginServer *gin.Engine) { exportGroup := ginServer.Group("/export/", model.CheckAuth) exportBaseDir := filepath.Join(util.TempDir, "export") - // 应下载而不是查看导出的文件 exportGroup.GET("/*filepath", func(c *gin.Context) { if strings.HasPrefix(c.Request.URL.Path, "/export/temp/") { - c.File(filepath.Join(util.TempDir, c.Request.URL.Path)) + tempBaseDir := filepath.Join(util.TempDir, "export", "temp") + relativePath := strings.TrimPrefix(c.Request.URL.Path, "/export/temp/") + relativePath = filepath.Clean(relativePath) + if strings.Contains(relativePath, "..") { + c.Status(http.StatusUnauthorized) + return + } + fullPath := filepath.Join(tempBaseDir, relativePath) + if !gulu.File.IsSubPath(tempBaseDir, fullPath) { + c.Status(http.StatusUnauthorized) + return + } + c.File(fullPath) return }