fix(lagoon/attach): StaticHandler sends the stored Content-Disposition and nosniff (quick-261105-oc8)
- attach.StaticHandler and attach.StaticHandlerPublic set X-Content-Type-Options: nosniff on every response - the stored disposition is read with one Attributes call after the is_public gate and sent on GET and HEAD; a value mime.ParseMediaType rejects is sent as attachment - blobs without a stored disposition are served as before - lagoon README, storage and attachments docs pages, surf uploads comment updated
This commit is contained in:
@@ -241,6 +241,41 @@ func TestStaticHandlerPublicLooksUpIsPublic(t *testing.T) {
|
||||
if code := get("/storage/uploads/abc/123/xyz/missing.jpg"); code != http.StatusNotFound {
|
||||
t.Fatalf("unknown disk_name status = %d, want 404", code)
|
||||
}
|
||||
|
||||
// The stored disposition and nosniff go through the is_public gate.
|
||||
htmlFile := attach.File{DiskName: "fed654cba.txt", FileName: "note.txt", FileSize: 1, ContentType: "text/html", IsPublic: &pub}
|
||||
if err := gdb.Create(&htmlFile).Error; err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := bucket.WriteAll(ctx, attach.BlobKey(htmlFile.DiskName), []byte("<html></html>"), &blob.WriterOptions{ContentType: "text/html", ContentDisposition: "attachment"}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
serve := func(path string) *http.Response {
|
||||
t.Helper()
|
||||
rr := httptest.NewRecorder()
|
||||
h.ServeHTTP(rr, httptest.NewRequest(http.MethodGet, path, nil))
|
||||
return rr.Result()
|
||||
}
|
||||
html := serve("/storage/uploads/fed/654/cba/fed654cba.txt")
|
||||
if html.StatusCode != http.StatusOK {
|
||||
t.Fatalf("public html status = %d, want 200", html.StatusCode)
|
||||
}
|
||||
if got := html.Header.Get("Content-Disposition"); got != "attachment" {
|
||||
t.Errorf("public html Content-Disposition = %q, want attachment", got)
|
||||
}
|
||||
if got := html.Header.Get("X-Content-Type-Options"); got != "nosniff" {
|
||||
t.Errorf("public html X-Content-Type-Options = %q, want nosniff", got)
|
||||
}
|
||||
jpeg := serve("/storage/uploads/abc/123/xyz/abc123xyz.jpg")
|
||||
if jpeg.StatusCode != http.StatusOK {
|
||||
t.Fatalf("public jpeg status = %d, want 200", jpeg.StatusCode)
|
||||
}
|
||||
if got := jpeg.Header.Get("X-Content-Type-Options"); got != "nosniff" {
|
||||
t.Errorf("public jpeg X-Content-Type-Options = %q, want nosniff", got)
|
||||
}
|
||||
if got := jpeg.Header.Values("Content-Disposition"); len(got) != 0 {
|
||||
t.Errorf("public jpeg Content-Disposition = %q, want none", got)
|
||||
}
|
||||
}
|
||||
|
||||
func assertFileRow(t *testing.T, gdb *gorm.DB, id uint, want bool) {
|
||||
|
||||
Reference in New Issue
Block a user