summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2026-04-29 23:32:47 +0300
committerPaul Buetow <paul@buetow.org>2026-04-29 23:32:47 +0300
commit504fbf825bc153c9744c191f903c517e6dcad0d4 (patch)
tree1b7b3566c6a895b383e72f1003798c19f1669480
parent9f0ceb6971c85f1fac8255bf420367b08f7e4acf (diff)
fix: prevent path traversal in UploadMedia
-rw-r--r--internal/service/media.go7
-rw-r--r--internal/service/media_test.go12
2 files changed, 19 insertions, 0 deletions
diff --git a/internal/service/media.go b/internal/service/media.go
index bf1bae0..71ca27c 100644
--- a/internal/service/media.go
+++ b/internal/service/media.go
@@ -245,6 +245,10 @@ func (s *mediaService) RestoreMedia(ctx context.Context, mediaID, userID int64)
}
func (s *mediaService) uniqueFilename(dir, filename string) string {
+ filename = filepath.Base(filename)
+ if filename == "." || filename == ".." || filename == "" {
+ return ""
+ }
ext := filepath.Ext(filename)
base := strings.TrimSuffix(filename, ext)
@@ -276,6 +280,9 @@ func (s *mediaService) UploadMedia(ctx context.Context, setID, userID int64, fil
}
path := s.uniqueFilename(dir, filename)
+ if !strings.HasPrefix(filepath.Clean(path), filepath.Clean(dir)+string(filepath.Separator)) {
+ return nil, errors.New("invalid filename")
+ }
f, err := os.Create(path)
if err != nil {
return nil, fmt.Errorf("create file: %w", err)
diff --git a/internal/service/media_test.go b/internal/service/media_test.go
index 7193ef7..edf2e27 100644
--- a/internal/service/media_test.go
+++ b/internal/service/media_test.go
@@ -575,6 +575,18 @@ func TestMediaService_UploadMedia(t *testing.T) {
setErr: errors.New("boom"),
wantErr: true,
},
+ {
+ name: "path traversal sanitized",
+ setExists: true,
+ filename: "../../etc/passwd",
+ wantErr: false,
+ },
+ {
+ name: "path traversal dotdot rejected",
+ setExists: true,
+ filename: "..",
+ wantErr: true,
+ },
}
for _, tt := range tests {