CVE-2026-33528
Description
GoDoxy is a reverse proxy and container orchestrator for self-hosters. Prior to version 0.27.5, the file content API endpoint at /api/v1/file/content is vulnerable to path traversal. The filename query parameter is passed directly to path.Join(common.ConfigBasePath, filename) where ConfigBasePath = "config" (a relative path). No sanitization or validation is applied beyond checking that the field is non-empty (binding:"required"). An authenticated attacker can use ../ sequences to read or write files outside the intended config/ directory, including TLS private keys, OAuth refresh tokens, and any file accessible to the container's UID. Version 0.27.5 fixes the issue.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
github.com/yusing/godoxyGo | < 0.27.5 | 0.27.5 |
Affected products
1Patches
1a541d75bb50ffix(api/file): prevent path traversal in file API
2 files changed · +77 −1
internal/api/v1/file/get.go+9 −1 modified@@ -1,6 +1,7 @@ package fileapi import ( + "io" "net/http" "os" "path" @@ -44,7 +45,14 @@ func Get(c *gin.Context) { return } - content, err := os.ReadFile(request.FileType.GetPath(request.Filename)) + f, err := os.OpenInRoot(".", request.FileType.GetPath(request.Filename)) + if err != nil { + c.Error(apitypes.InternalServerError(err, "failed to open root")) + return + } + defer f.Close() + + content, err := io.ReadAll(f) if err != nil { c.Error(apitypes.InternalServerError(err, "failed to read file")) return
internal/api/v1/file/get_test.go+68 −0 added@@ -0,0 +1,68 @@ +package fileapi_test + +import ( + "net/http" + "net/http/httptest" + "net/url" + "os" + "testing" + + "github.com/gin-gonic/gin" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + api "github.com/yusing/godoxy/internal/api" + fileapi "github.com/yusing/godoxy/internal/api/v1/file" + "github.com/yusing/goutils/fs" +) + +func TestGet_PathTraversalBlocked(t *testing.T) { + gin.SetMode(gin.TestMode) + + files, err := fs.ListFiles("..", 1, false) + require.NoError(t, err) + + require.Greater(t, len(files), 0, "no files found") + + relativePath := files[0] + + fileContent, err := os.ReadFile(relativePath) + require.NoError(t, err) + + r := gin.New() + r.Use(api.ErrorHandler()) + r.GET("/api/v1/file/content", fileapi.Get) + + tests := []struct { + name string + filename string + queryEscaped bool + }{ + { + name: "dotdot_traversal", + filename: relativePath, + }, + { + name: "url_encoded_dotdot_traversal", + filename: relativePath, + queryEscaped: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + filename := tt.filename + if tt.queryEscaped { + filename = url.QueryEscape(filename) + } + + url := "/api/v1/file/content?type=config&filename=" + filename + req := httptest.NewRequest(http.MethodGet, url, nil) + w := httptest.NewRecorder() + r.ServeHTTP(w, req) + + // "Blocked" means we should never successfully read the outside file. + assert.NotEqual(t, http.StatusOK, w.Code) + assert.NotEqual(t, fileContent, w.Body.String()) + }) + } +}
Vulnerability mechanics
Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
5- github.com/yusing/godoxy/commit/a541d75bb50f1b542c096d8bc8082c3549f5c059nvdPatchWEB
- github.com/yusing/godoxy/security/advisories/GHSA-4753-cmc8-8j9vnvdExploitMitigationVendor AdvisoryWEB
- github.com/advisories/GHSA-4753-cmc8-8j9vghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2026-33528ghsaADVISORY
- github.com/yusing/godoxy/releases/tag/v0.27.5nvdProductRelease NotesWEB
News mentions
0No linked articles in our index yet.