CVE-2023-41318: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting') (CWE-79)
value: matrix-media-repo is a highly customizable multi-domain media repository for the Matrix chat ecosystem. In affected versions an attacker could upload a malicious piece of media to the media repo, which would then be served with `Content-Disposition: inline` upon download. This vulnerability could be leveraged to execute scripts embedded in SVG content. Commits `77ec235` and `bf8abdd` fix the issue and are included in the 1.3.0 release. Operators should upgrade to v1.3.0 as soon as possible. Operators unable to upgrade should override the `Content-Disposition` header returned by matrix-media-repo as a workaround.
CWE description: The product does not neutralize or incorrectly neutralizes user-controllable input before it is placed in output that is used as a web page that is served to other users.
CVSS v3 base score: 5.4
Published: 2023-09-08T20:15Z
Repository: https://github.com/turt2live/matrix-media-repo
Language: Go
Files changed: api/_routers/98-use-rcontext.go, util/mime.go
Commit date: 2023-09-05 13:09:04 -0600
Commit message: Fix Content-Disposition handling

Diff: diff --git a/api/_routers/98-use-rcontext.go b/api/_routers/98-use-rcontext.go
index bd6bf03..18c678c 100644
--- a/api/_routers/98-use-rcontext.go
+++ b/api/_routers/98-use-rcontext.go
@@ -110,11 +110,11 @@ beforeParseDownload:
 			disposition = "inline"
 		} else if disposition == "infer" {
 			if contentType == "" {
 				disposition = "attachment"
 			} else {
-				if util.HasAnyPrefix(contentType, []string{"image/", "audio/", "video/", "text/plain"}) {
+				if util.CanInline(contentType) {
 					disposition = "inline"
 				} else {
 					disposition = "attachment"
 				}
 			}
diff --git a/util/mime.go b/util/mime.go
index 5887654..8d34d03 100644
--- a/util/mime.go
+++ b/util/mime.go
@@ -14,5 +14,41 @@ func ExtensionForContentType(ct string) string {
 	if len(exts) > 0 {
 		return exts[0]
 	}
 	return ".bin"
 }
+
+func CanInline(ct string) bool {
+	ct = FixContentType(ct)
+	return ArrayContains(InlineContentTypes, ct)
+}
+
+var InlineContentTypes = []string{
+	// Types are inherited from https://github.com/matrix-org/synapse/pull/15988
+
+	"text/css",
+	"text/plain",
+	"text/csv",
+	"application/json",
+	"application/ld+json",
+	"image/jpeg",
+	"image/gif",
+	"image/png",
+	"image/apng",
+	"image/webp",
+	"image/avif",
+	"video/mp4",
+	"video/webm",
+	"video/ogg",
+	"video/quicktime",
+	"audio/mp4",
+	"audio/webm",
+	"audio/aac",
+	"audio/mpeg",
+	"audio/ogg",
+	"audio/wave",
+	"audio/wav",
+	"audio/x-wav",
+	"audio/x-pn-wav",
+	"audio/flac",
+	"audio/x-flac",
+}

Vulnerable code: 				if util.HasAnyPrefix(contentType, []string{"image/", "audio/", "video/", "text/plain"}) {
Fixed code: 				if util.CanInline(contentType) {

func CanInline(ct string) bool {
	ct = FixContentType(ct)
	return ArrayContains(InlineContentTypes, ct)
}

var InlineContentTypes = []string{
	// Types are inherited from https://github.com/matrix-org/synapse/pull/15988

	"text/css",
	"text/plain",
	"text/csv",
	"application/json",
	"application/ld+json",
	"image/jpeg",
	"image/gif",
	"image/png",
	"image/apng",
	"image/webp",
	"image/avif",
	"video/mp4",
	"video/webm",
	"video/ogg",
	"video/quicktime",
	"audio/mp4",
	"audio/webm",
	"audio/aac",
	"audio/mpeg",
	"audio/ogg",
	"audio/wave",
	"audio/wav",
	"audio/x-wav",
	"audio/x-pn-wav",
	"audio/flac",
	"audio/x-flac",
}