diff --git a/custom/conf/app.example.ini b/custom/conf/app.example.ini
index 70db76cf7f..2b5b518a19 100644
--- a/custom/conf/app.example.ini
+++ b/custom/conf/app.example.ini
@@ -1938,7 +1938,7 @@ LEVEL = Info
 ;ENABLED = true
 ;;
 ;; Comma-separated list of allowed file extensions (`.zip`), mime types (`text/plain`) or wildcard type (`image/*`, `audio/*`, `video/*`). Empty value or `*/*` allows all types.
-;ALLOWED_TYPES = .cpuprofile,.csv,.dmp,.docx,.fodg,.fodp,.fods,.fodt,.gif,.gz,.jpeg,.jpg,.json,.jsonc,.log,.md,.mov,.mp4,.odf,.odg,.odp,.ods,.odt,.patch,.pdf,.png,.pptx,.svg,.tgz,.txt,.webm,.xls,.xlsx,.zip
+;ALLOWED_TYPES = .avif,.cpuprofile,.csv,.dmp,.docx,.fodg,.fodp,.fods,.fodt,.gif,.gz,.jpeg,.jpg,.json,.jsonc,.log,.md,.mov,.mp4,.odf,.odg,.odp,.ods,.odt,.patch,.pdf,.png,.pptx,.svg,.tgz,.txt,.webm,.xls,.xlsx,.zip
 ;;
 ;; Max size of each file. Defaults to 2048MB
 ;MAX_SIZE = 2048
@@ -1976,7 +1976,7 @@ LEVEL = Info
 ;; Url lookup for the minio bucket only available when STORAGE_TYPE is `minio`
 ;; Available values: auto, dns, path
 ;; If empty, it behaves the same as "auto" was set
-;MINIO_BUCKET_LOOKUP = 
+;MINIO_BUCKET_LOOKUP =
 ;;
 ;; Minio location to create bucket only available when STORAGE_TYPE is `minio`
 ;MINIO_LOCATION = us-east-1
@@ -2703,7 +2703,7 @@ LEVEL = Info
 ;; Url lookup for the minio bucket only available when STORAGE_TYPE is `minio`
 ;; Available values: auto, dns, path
 ;; If empty, it behaves the same as "auto" was set
-;MINIO_BUCKET_LOOKUP = 
+;MINIO_BUCKET_LOOKUP =
 ;;
 ;; Minio location to create bucket only available when STORAGE_TYPE is `minio`
 ;MINIO_LOCATION = us-east-1
diff --git a/modules/setting/attachment.go b/modules/setting/attachment.go
index 4255ac985e..956525f0db 100644
--- a/modules/setting/attachment.go
+++ b/modules/setting/attachment.go
@@ -12,7 +12,7 @@ var Attachment = struct {
 	Enabled      bool
 }{
 	Storage:      &Storage{},
-	AllowedTypes: ".cpuprofile,.csv,.dmp,.docx,.fodg,.fodp,.fods,.fodt,.gif,.gz,.jpeg,.jpg,.json,.jsonc,.log,.md,.mov,.mp4,.odf,.odg,.odp,.ods,.odt,.patch,.pdf,.png,.pptx,.svg,.tgz,.txt,.webm,.webp,.xls,.xlsx,.zip",
+	AllowedTypes: ".avif,.cpuprofile,.csv,.dmp,.docx,.fodg,.fodp,.fods,.fodt,.gif,.gz,.jpeg,.jpg,.json,.jsonc,.log,.md,.mov,.mp4,.odf,.odg,.odp,.ods,.odt,.patch,.pdf,.png,.pptx,.svg,.tgz,.txt,.webm,.webp,.xls,.xlsx,.zip",
 	MaxSize:      2048,
 	MaxFiles:     5,
 	Enabled:      true,
@@ -25,7 +25,7 @@ func loadAttachmentFrom(rootCfg ConfigProvider) (err error) {
 		return err
 	}
 
-	Attachment.AllowedTypes = sec.Key("ALLOWED_TYPES").MustString(".cpuprofile,.csv,.dmp,.docx,.fodg,.fodp,.fods,.fodt,.gif,.gz,.jpeg,.jpg,.json,.jsonc,.log,.md,.mov,.mp4,.odf,.odg,.odp,.ods,.odt,.patch,.pdf,.png,.pptx,.svg,.tgz,.txt,.webm,.webp,.xls,.xlsx,.zip")
+	Attachment.AllowedTypes = sec.Key("ALLOWED_TYPES").MustString(".avif,.cpuprofile,.csv,.dmp,.docx,.fodg,.fodp,.fods,.fodt,.gif,.gz,.jpeg,.jpg,.json,.jsonc,.log,.md,.mov,.mp4,.odf,.odg,.odp,.ods,.odt,.patch,.pdf,.png,.pptx,.svg,.tgz,.txt,.webm,.webp,.xls,.xlsx,.zip")
 	Attachment.MaxSize = sec.Key("MAX_SIZE").MustInt64(2048)
 	Attachment.MaxFiles = sec.Key("MAX_FILES").MustInt(5)
 	Attachment.Enabled = sec.Key("ENABLED").MustBool(true)
diff --git a/modules/typesniffer/typesniffer.go b/modules/typesniffer/typesniffer.go
index 6aec5c285e..64037af8d3 100644
--- a/modules/typesniffer/typesniffer.go
+++ b/modules/typesniffer/typesniffer.go
@@ -20,6 +20,8 @@ const sniffLen = 1024
 const (
 	// SvgMimeType MIME type of SVG images.
 	SvgMimeType = "image/svg+xml"
+	// AvifMimeType MIME type of AVIF images
+	AvifMimeType = "image/avif"
 	// ApplicationOctetStream MIME type of binary files.
 	ApplicationOctetStream = "application/octet-stream"
 )
@@ -106,6 +108,12 @@ func DetectContentType(data []byte) SniffedType {
 		}
 	}
 
+	// AVIF is unsuported by http.DetectContentType
+	// Signature taken from https://stackoverflow.com/a/68322450
+	if bytes.Index(data, []byte("ftypavif")) == 4 {
+		ct = AvifMimeType
+	}
+
 	if strings.HasPrefix(ct, "audio/") && bytes.HasPrefix(data, []byte("ID3")) {
 		// The MP3 detection is quite inaccurate, any content with "ID3" prefix will result in "audio/mpeg".
 		// So remove the "ID3" prefix and detect again, if result is text, then it must be text content.
diff --git a/modules/typesniffer/typesniffer_test.go b/modules/typesniffer/typesniffer_test.go
index f6fa07ee7f..8d80b4ddb4 100644
--- a/modules/typesniffer/typesniffer_test.go
+++ b/modules/typesniffer/typesniffer_test.go
@@ -135,3 +135,13 @@ func TestDetectContentTypeOgg(t *testing.T) {
 	require.NoError(t, err)
 	assert.True(t, st.IsVideo())
 }
+
+func TestDetectContentTypeAvif(t *testing.T) {
+	avifImage, err := hex.DecodeString("000000206674797061766966")
+	require.NoError(t, err)
+
+	st, err := DetectContentTypeFromReader(bytes.NewReader(avifImage))
+	require.NoError(t, err)
+
+	assert.True(t, st.IsImage())
+}