Skip to content

Commit 022e1a9

Browse files
committed
Support for whitelisting extensions/mimetype
1 parent e0968d5 commit 022e1a9

5 files changed

Lines changed: 46 additions & 1 deletion

File tree

deployment/community/.env.template

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,10 @@ LOCAL_PROJECTS=/data
109109

110110
#BLACKLIST='.mergin/, .DS_Store, .directory' # cast=Csv()
111111

112+
# extra file types to permit beyond the default block-list (e.g. scripts)
113+
#UPLOAD_EXTENSIONS_WHITELIST='' # cast=Csv()
114+
#UPLOAD_MIME_TYPES_WHITELIST='' # cast=Csv()
115+
112116
#FILE_EXPIRATION=48 * 3600 # for clean up of old files where diffs were applied, in seconds
113117

114118
#LOCKFILE_EXPIRATION=300 # in seconds

server/mergin/sync/config.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,5 +82,13 @@ class Configuration(object):
8282
)
8383
# files that should be ignored during extension and MIME type checks
8484
UPLOAD_FILES_WHITELIST = config("UPLOAD_FILES_WHITELIST", default="", cast=Csv())
85+
# extra extensions to permit beyond the default block-list
86+
UPLOAD_EXTENSIONS_WHITELIST = config(
87+
"UPLOAD_EXTENSIONS_WHITELIST", default="", cast=Csv()
88+
)
89+
# extra MIME types to permit beyond the default block-list
90+
UPLOAD_MIME_TYPES_WHITELIST = config(
91+
"UPLOAD_MIME_TYPES_WHITELIST", default="", cast=Csv()
92+
)
8593
# max batch size for fetch projects in batch endpoint
8694
MAX_BATCH_SIZE = config("MAX_BATCH_SIZE", default=100, cast=int)

server/mergin/sync/files.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,7 @@ def validate(self, data, **kwargs):
224224

225225
if not is_supported_extension(file_path):
226226
raise ValidationError(
227-
f"Unsupported file type detected: '{file_path}'. "
227+
f"stop Unsupported file type detected: '{file_path}'. "
228228
f"Please remove the file or try compressing it into a ZIP file before uploading.",
229229
)
230230
# new checks must restrict only new files not to block existing projects

server/mergin/sync/utils.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -315,6 +315,8 @@ def is_supported_extension(filepath) -> bool:
315315
if check_skip_validation(filepath):
316316
return True
317317
ext = os.path.splitext(filepath)[1].lower()
318+
if ext in {e.lower() for e in Configuration.UPLOAD_EXTENSIONS_WHITELIST}:
319+
return True
318320
return ext and ext not in FORBIDDEN_EXTENSIONS
319321

320322

@@ -493,6 +495,8 @@ def is_supported_type(filepath) -> bool:
493495
if check_skip_validation(filepath):
494496
return True
495497
mime_type = get_mimetype(filepath)
498+
if mime_type in Configuration.UPLOAD_MIME_TYPES_WHITELIST:
499+
return True
496500
return mime_type.startswith("image/") or mime_type not in FORBIDDEN_MIME_TYPES
497501

498502

server/mergin/tests/test_utils.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -402,3 +402,32 @@ def test_mime_type_validation_skip():
402402

403403
# Should be forbidden
404404
assert not is_supported_type("other.js")
405+
406+
407+
def test_allowed_extensions_override():
408+
"""Extensions in UPLOAD_EXTENSIONS_WHITELIST are accepted even though they are in FORBIDDEN_EXTENSIONS."""
409+
with patch(
410+
"mergin.sync.utils.Configuration.UPLOAD_EXTENSIONS_WHITELIST", [".py", ".sh"]
411+
):
412+
# forbidden by default, now explicitly allowed
413+
assert is_supported_extension("model.py")
414+
assert is_supported_extension("scripts/deploy.sh")
415+
# match is case-insensitive
416+
assert is_supported_extension("MODEL.PY")
417+
# extensions not in the override stay blocked
418+
assert not is_supported_extension("malware.exe")
419+
assert not is_supported_extension("app.js")
420+
421+
422+
def test_allowed_mime_types_override():
423+
"""MIME types in UPLOAD_MIME_TYPES_WHITELIST are accepted even though they are in FORBIDDEN_MIME_TYPES."""
424+
with patch("mergin.sync.utils.get_mimetype", return_value="text/x-shellscript"):
425+
# blocked by default
426+
with patch("mergin.sync.utils.Configuration.UPLOAD_MIME_TYPES_WHITELIST", []):
427+
assert not is_supported_type("deploy.sh")
428+
# explicitly allowed
429+
with patch(
430+
"mergin.sync.utils.Configuration.UPLOAD_MIME_TYPES_WHITELIST",
431+
["text/x-shellscript"],
432+
):
433+
assert is_supported_type("deploy.sh")

0 commit comments

Comments
 (0)