From 2d0b90c967b24ba4558540d9db985b121b77f455 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Sat, 17 Aug 2019 18:10:17 +0800 Subject: [PATCH] Fix upload file type check (#7890) * fix upload file type check * make the function simple and added tests * Update comment as per @silverwind --- modules/upload/filetype.go | 17 +++++------- modules/upload/filetype_test.go | 47 +++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+), 10 deletions(-) create mode 100644 modules/upload/filetype_test.go diff --git a/modules/upload/filetype.go b/modules/upload/filetype.go index 1ec7324ed3..2ab326d116 100644 --- a/modules/upload/filetype.go +++ b/modules/upload/filetype.go @@ -31,19 +31,16 @@ func (err ErrFileTypeForbidden) Error() string { func VerifyAllowedContentType(buf []byte, allowedTypes []string) error { fileType := http.DetectContentType(buf) - allowed := false for _, t := range allowedTypes { t := strings.Trim(t, " ") - if t == "*/*" || t == fileType { - allowed = true - break + + if t == "*/*" || t == fileType || + // Allow directives after type, like 'text/plain; charset=utf-8' + strings.HasPrefix(fileType, t+";") { + return nil } } - if !allowed { - log.Info("Attachment with type %s blocked from upload", fileType) - return ErrFileTypeForbidden{Type: fileType} - } - - return nil + log.Info("Attachment with type %s blocked from upload", fileType) + return ErrFileTypeForbidden{Type: fileType} } diff --git a/modules/upload/filetype_test.go b/modules/upload/filetype_test.go new file mode 100644 index 0000000000..f93a1c5cc3 --- /dev/null +++ b/modules/upload/filetype_test.go @@ -0,0 +1,47 @@ +// Copyright 2019 The Gitea Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package upload + +import ( + "bytes" + "compress/gzip" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestUpload(t *testing.T) { + testContent := []byte(`This is a plain text file.`) + var b bytes.Buffer + w := gzip.NewWriter(&b) + w.Write(testContent) + w.Close() + + kases := []struct { + data []byte + allowedTypes []string + err error + }{ + { + data: testContent, + allowedTypes: []string{"text/plain"}, + err: nil, + }, + { + data: testContent, + allowedTypes: []string{"application/x-gzip"}, + err: ErrFileTypeForbidden{"text/plain; charset=utf-8"}, + }, + { + data: b.Bytes(), + allowedTypes: []string{"application/x-gzip"}, + err: nil, + }, + } + + for _, kase := range kases { + assert.Equal(t, kase.err, VerifyAllowedContentType(kase.data, kase.allowedTypes)) + } +}