mirror of
https://github.com/yusing/godoxy.git
synced 2026-03-21 08:39:03 +01:00
Use os.OpenRoot to restrict file access to the application root, preventing directory traversal attacks through the file download endpoint. Also add test to verify path traversal attempts are blocked.
69 lines
1.5 KiB
Go
69 lines
1.5 KiB
Go
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())
|
|
})
|
|
}
|
|
}
|