diff --git a/server/server.go b/server/server.go index 5c4fd7333e..5da5835a34 100644 --- a/server/server.go +++ b/server/server.go @@ -12,6 +12,7 @@ import ( "os" "os/exec" "path" + "path/filepath" "regexp" "strings" "time" @@ -825,8 +826,18 @@ func indexFilePath(srcPath string, baseHRef string) (string, error) { return filePath, nil } -func fileExists(filename string) bool { - info, err := os.Stat(filename) +func fileExists(dir, filename string) bool { + // We make sure that the resulting path is within the directory we intend to + // serve content from. path.Join() will normalize the path. + abs, err := filepath.Abs(dir) + if err != nil { + return false + } + fp := path.Join(abs, filename) + if !strings.HasPrefix(fp, abs) { + return false + } + info, err := os.Stat(fp) if os.IsNotExist(err) { return false } @@ -843,7 +854,8 @@ func (server *ArgoCDServer) newStaticAssetsHandler(dir string, baseHRef string) break } } - fileRequest := r.URL.Path != "/index.html" && fileExists(path.Join(dir, r.URL.Path)) + + fileRequest := r.URL.Path != "/index.html" && fileExists(dir, r.URL.Path) // Set X-Frame-Options according to configuration if server.XFrameOptions != "" { diff --git a/server/server_test.go b/server/server_test.go index 48c638b068..226b1ca01d 100644 --- a/server/server_test.go +++ b/server/server_test.go @@ -546,3 +546,24 @@ func TestInitializeDefaultProject_ProjectAlreadyInitialized(t *testing.T) { assert.Equal(t, proj.Spec, existingDefaultProject.Spec) } + +func TestFileExists(t *testing.T) { + t.Run("File exists and path is within dir", func(t *testing.T) { + exists := fileExists(".", "server.go") + assert.True(t, exists) + exists = fileExists(".", "account/account.go") + assert.True(t, exists) + }) + t.Run("File does not exist", func(t *testing.T) { + exists := fileExists(".", "notexist.go") + assert.False(t, exists) + }) + t.Run("Dir does not exist", func(t *testing.T) { + exists := fileExists("/notexisting", "server.go") + assert.False(t, exists) + }) + t.Run("File outside of dir", func(t *testing.T) { + exists := fileExists(".", "../reposerver/server.go") + assert.False(t, exists) + }) +}