Monorepo for Tangled
tangled.org
1package repo
2
3import (
4 "mime"
5 "strings"
6 "testing"
7)
8
9func TestSafeBinaryMIMEType(t *testing.T) {
10 allowed := []string{
11 "image/png",
12 "image/jpeg",
13 "image/gif",
14 "image/webp",
15 "image/avif",
16 "video/mp4",
17 "video/webm",
18 "video/ogg",
19 }
20 for _, ct := range allowed {
21 if !safeBinaryMIMEType(ct) {
22 t.Errorf("expected %q to be allowed, but it was not", ct)
23 }
24 }
25
26 rejected := []string{
27 // SVG must be rejected — it supports embedded scripts.
28 "image/svg+xml",
29 // Other XML-based or scriptable types.
30 "image/svg",
31 "application/pdf",
32 "application/octet-stream",
33 "text/html",
34 "text/javascript",
35 // Empty / garbage.
36 "",
37 "image/",
38 "video/",
39 }
40 for _, ct := range rejected {
41 if safeBinaryMIMEType(ct) {
42 t.Errorf("expected %q to be rejected, but it was allowed", ct)
43 }
44 }
45}
46
47// TestBlobMIMENormalization verifies that mime.ParseMediaType strips
48// parameters before classification, closing bypass attempts such as
49// "image/svg+xml; charset=utf-8".
50func TestBlobMIMENormalization(t *testing.T) {
51 cases := []struct {
52 raw string
53 wantSafeBinary bool
54 wantTextual bool
55 }{
56 // Parameters must not smuggle SVG past the allowlist.
57 {"image/svg+xml; charset=utf-8", false, false},
58 {"image/svg+xml; innocent=param", false, false},
59 // Parameters on safe types should still be allowed.
60 {"image/png; q=0.9", true, false},
61 // Parameters on textual types.
62 {"text/plain; charset=utf-8", false, true},
63 {"application/json; charset=utf-8", false, true},
64 }
65
66 for _, tc := range cases {
67 mediaType, _, _ := mime.ParseMediaType(tc.raw)
68 gotSafeBinary := safeBinaryMIMEType(mediaType)
69 gotTextual := strings.HasPrefix(mediaType, "text/") || isTextualMimeType(mediaType)
70
71 if gotSafeBinary != tc.wantSafeBinary {
72 t.Errorf("safeBinaryMIMEType(%q): got %v, want %v (parsed as %q)",
73 tc.raw, gotSafeBinary, tc.wantSafeBinary, mediaType)
74 }
75 if gotTextual != tc.wantTextual {
76 t.Errorf("isTextual(%q): got %v, want %v (parsed as %q)",
77 tc.raw, gotTextual, tc.wantTextual, mediaType)
78 }
79 }
80}