fix(05): WR-04 restrict thumb mode and ext to [a-z0-9]+ before building blob keys
This commit is contained in:
@@ -5,6 +5,8 @@ import (
|
||||
"image"
|
||||
"image/color"
|
||||
"image/jpeg"
|
||||
"io"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"gocloud.dev/blob"
|
||||
@@ -19,6 +21,43 @@ func TestThumbFilename(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestThumbFilenameRejectsUnsafeTokens(t *testing.T) {
|
||||
for _, tc := range []struct{ mode, ext string }{
|
||||
{"../../secret", "jpg"},
|
||||
{"auto", "../jpg"},
|
||||
{"a/b", "jpg"},
|
||||
{"auto", "j.pg"},
|
||||
{"", ""},
|
||||
{"Crop", "JPG"},
|
||||
} {
|
||||
got := ThumbFilename(42, 200, 200, 0, 0, tc.mode, tc.ext)
|
||||
if strings.ContainsAny(got, `/\`) || strings.Contains(got, "..") {
|
||||
t.Fatalf("mode=%q ext=%q produced unsafe name %q", tc.mode, tc.ext, got)
|
||||
}
|
||||
if !strings.HasPrefix(got, "thumb_42_200_200_0_0_") {
|
||||
t.Fatalf("mode=%q ext=%q name %q lost its prefix", tc.mode, tc.ext, got)
|
||||
}
|
||||
}
|
||||
if got := ThumbFilename(42, 200, 200, 0, 0, "../../secret", "jpg"); got != "thumb_42_200_200_0_0_auto.jpg" {
|
||||
t.Fatalf("unsafe mode coerced to %q", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFileThumbRejectsTraversalMode(t *testing.T) {
|
||||
bucket := memblob.OpenBucket(nil)
|
||||
defer bucket.Close()
|
||||
f := &File{ID: 42, DiskName: "abc123xyz789.jpg"}
|
||||
for _, mode := range []string{"../../secret", "a/b", "auto.jpg", "cr op"} {
|
||||
if _, err := f.Thumb(t.Context(), bucket, 200, 200, mode); err == nil {
|
||||
t.Fatalf("mode %q must be rejected", mode)
|
||||
}
|
||||
}
|
||||
iter := bucket.List(nil)
|
||||
if obj, err := iter.Next(t.Context()); err != io.EOF {
|
||||
t.Fatalf("rejected modes must write nothing, found %v (err %v)", obj, err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPartitionDirectory(t *testing.T) {
|
||||
got := PartitionDirectory("abc123xyz.jpg")
|
||||
const want = "abc/123/xyz/"
|
||||
|
||||
Reference in New Issue
Block a user