From accd80c99e0eb01aeeb79b6b089a1551eaf0ece1 Mon Sep 17 00:00:00 2001 From: Fabian Braun Date: Fri, 7 Jul 2023 21:12:23 +0200 Subject: [PATCH 1/8] Fix #1377 --- filer/models/foldermodels.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/filer/models/foldermodels.py b/filer/models/foldermodels.py index a9c1e851e..54fa9c5a4 100644 --- a/filer/models/foldermodels.py +++ b/filer/models/foldermodels.py @@ -6,7 +6,7 @@ from django.urls import reverse from django.utils.functional import cached_property from django.utils.html import format_html, format_html_join -from django.utils.translation import gettext as _ +from django.utils.translation import gettext_lazy as _ from .. import settings as filer_settings from . import mixins From 3a9d5c7ed8103a05648d87fa1e88552f76d8c310 Mon Sep 17 00:00:00 2001 From: Fabian Braun Date: Thu, 22 Aug 2024 21:00:52 +0200 Subject: [PATCH 2/8] Bump to 3.2.0 --- CHANGELOG.rst | 12 ++++++++++++ filer/__init__.py | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 55b601400..2ddb19915 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -2,6 +2,18 @@ CHANGELOG ========= +3.2.0 (2024-08-23) +================== + +* feat: Add cache for permission checks by @fsbraun in https://github.com/django-cms/django-filer/pull/1486 +* fix: Reduce number of thumbnails created for admin, avoid admin thumbnails for svg files by @fsbraun in https://github.com/django-cms/django-filer/pull/1490 +* fix: Allow ``Image.MAX_IMAGE_PIXELS`` to be ``None`` by @fsbraun in https://github.com/django-cms/django-filer/pull/1475 +* docs: Update extending_filer.rst by @DmytroLitvinov in https://github.com/django-cms/django-filer/pull/1488 + +**New contributor:** + +* @DmytroLitvinov made their first contribution in https://github.com/django-cms/django-filer/pull/1488 + 3.1.4 (2024-07-15) ================== diff --git a/filer/__init__.py b/filer/__init__.py index 7bd0b5d4e..9208292c2 100644 --- a/filer/__init__.py +++ b/filer/__init__.py @@ -13,4 +13,4 @@ 8. Publish the release and it will automatically release to pypi """ -__version__ = '3.1.4' +__version__ = '3.2.0' From e0e7f34a070e7f75d6f42e6acc308c9b26efe777 Mon Sep 17 00:00:00 2001 From: Fabian Braun Date: Mon, 18 Nov 2024 18:30:55 +0100 Subject: [PATCH 3/8] fix: Deny upload of binary or unknown file types --- docs/validation.rst | 47 ++++++++++++++++++++++++++++---- filer/contrib/clamav/__init__.py | 0 filer/settings.py | 1 + 3 files changed, 43 insertions(+), 5 deletions(-) create mode 100644 filer/contrib/clamav/__init__.py diff --git a/docs/validation.rst b/docs/validation.rst index 1019f02a3..d027556cf 100644 --- a/docs/validation.rst +++ b/docs/validation.rst @@ -54,9 +54,9 @@ files with the mime type ``image/svg+xml``. Those files are dangerous since they are executed by a browser without any warnings. Validation hooks do not restrict the upload of other executable files -(like ``*.exe`` or shell scripts). Those are not automatically executed +(like ``*.exe`` or shell scripts). **Those are not automatically executed by the browser but still present a point of attack, if a user saves them -to disk and executes them locally. +to disk and executes them locally.** You can release validation restrictions by setting ``FILER_REMOVE_FILE_VALIDATORS`` to a list of mime types to be removed from @@ -111,7 +111,7 @@ This just rejects any file for upload. By default this happens for HTML files This validator rejects any SVG file that contains the bytes ```_ +you can add a validator that checks for viruses in uploaded files. + +.. code-block:: python + + FILER_ADD_FILE_VALIDATORS = { + "application/octet-stream": ["my_validator_app.validators.validate_octet_stream"], + } + + +.. code-block:: python + + def validate_octet_stream(file_name: str, file: typing.IO, owner: User, mime_type: str) -> None: + """Octet streams are binary files without a specific mime type. They are run through + a virus check.""" + try: + from django_clamd.validators import validate_file_infection + + validate_file_infection(file) + except (ModuleNotFoundError, ImportError): + raise FileValidationError( + _('File "{file_name}": Virus check for binary/unknown file not available').format(file_name=file_name) + ) + +.. note:: + + Virus-checked files still might contain executable code. While the code is not + executed by the browser, a user might still download the file and execute it + manually. diff --git a/filer/contrib/clamav/__init__.py b/filer/contrib/clamav/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/filer/settings.py b/filer/settings.py index c0f700838..d6ec392b1 100644 --- a/filer/settings.py +++ b/filer/settings.py @@ -292,6 +292,7 @@ def update_server_settings(settings, defaults, s, t): FILE_VALIDATORS = { "text/html": ["filer.validation.deny_html"], "image/svg+xml": ["filer.validation.validate_svg"], + "application/octet-stream": ["filer.validation.deny"], } remove_mime_types = getattr(settings, "FILER_REMOVE_FILE_VALIDATORS", []) From 61b23c5415e0b1bef022d5d5541b218a3c83b7f7 Mon Sep 17 00:00:00 2001 From: Fabian Braun Date: Mon, 18 Nov 2024 18:43:21 +0100 Subject: [PATCH 4/8] Update tests --- filer/cache.py | 2 +- tests/test_admin.py | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/filer/cache.py b/filer/cache.py index ee41a0fb6..b5d4fc441 100644 --- a/filer/cache.py +++ b/filer/cache.py @@ -1,7 +1,7 @@ import typing -from django.db.models import Model from django.core.cache import cache +from django.db.models import Model UserModel = typing.TypeVar('UserModel', bound=Model) diff --git a/tests/test_admin.py b/tests/test_admin.py index 6dea14f06..13c1f2f6b 100644 --- a/tests/test_admin.py +++ b/tests/test_admin.py @@ -3,6 +3,7 @@ import django import django.core.files +from django.apps import apps from django.conf import settings from django.contrib import admin from django.contrib.admin import helpers @@ -484,6 +485,10 @@ def test_filer_upload_file_no_folder(self, extra_headers={}): self.assertEqual(stored_image.mime_type, 'image/jpeg') def test_filer_upload_binary_data(self, extra_headers={}): + config = apps.get_app_config("filer") + + validators = config.FILE_VALIDATORS # Remember the validators + config.FILE_VALIDATORS = {} # Remove deny for application/octet-stream self.assertEqual(File.objects.count(), 0) with open(self.binary_filename, 'rb') as fh: file_obj = django.core.files.File(fh) @@ -494,6 +499,8 @@ def test_filer_upload_binary_data(self, extra_headers={}): 'jsessionid': self.client.session.session_key } self.client.post(url, post_data, **extra_headers) + config.FILE_VALIDATORS = validators # Reset validators + self.assertEqual(Image.objects.count(), 0) self.assertEqual(File.objects.count(), 1) stored_file = File.objects.first() From b591f03f13a85a8cf6d0be8a2928fe15c33302e3 Mon Sep 17 00:00:00 2001 From: Fabian Braun Date: Mon, 18 Nov 2024 20:26:00 +0100 Subject: [PATCH 5/8] Update validation.rst --- docs/validation.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/validation.rst b/docs/validation.rst index d027556cf..e81ef6808 100644 --- a/docs/validation.rst +++ b/docs/validation.rst @@ -272,6 +272,7 @@ you can add a validator that checks for viruses in uploaded files. .. code-block:: python + FILER_REMOVE_FILE_VALIDATORS = ["application/octet-stream"] FILER_ADD_FILE_VALIDATORS = { "application/octet-stream": ["my_validator_app.validators.validate_octet_stream"], } From abc251e70420a4d22d26aa5bcd353256a49edf0b Mon Sep 17 00:00:00 2001 From: Fabian Braun Date: Tue, 19 Nov 2024 09:12:38 +0100 Subject: [PATCH 6/8] Update docs/validation.rst Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com> --- docs/validation.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/validation.rst b/docs/validation.rst index e81ef6808..3d43cde48 100644 --- a/docs/validation.rst +++ b/docs/validation.rst @@ -267,7 +267,7 @@ validator function for all relevant mime types. Checking uploads for viruses using ClamAV ----------------------------------------- -If you have ClamAV installed an use `django-clamd `_ +If you have ClamAV installed and use `django-clamd `_ you can add a validator that checks for viruses in uploaded files. .. code-block:: python From 862bd1b9e75b906c57204c4c301955afb841ef1e Mon Sep 17 00:00:00 2001 From: Fabian Braun Date: Tue, 19 Nov 2024 09:16:56 +0100 Subject: [PATCH 7/8] Add test that binary uploads fail by default --- tests/test_admin.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/tests/test_admin.py b/tests/test_admin.py index 13c1f2f6b..b10fb49db 100644 --- a/tests/test_admin.py +++ b/tests/test_admin.py @@ -507,6 +507,21 @@ def test_filer_upload_binary_data(self, extra_headers={}): self.assertEqual(stored_file.original_filename, self.binary_name) self.assertEqual(stored_file.mime_type, 'application/octet-stream') + def test_filer_upload_binary_data_fails_by_default(self, extra_headers={}): + self.assertEqual(File.objects.count(), 0) + with open(self.binary_filename, 'rb') as fh: + file_obj = django.core.files.File(fh) + url = reverse('admin:filer-ajax_upload') + post_data = { + 'Filename': self.binary_name, + 'Filedata': file_obj, + 'jsessionid': self.client.session.session_key + } + self.client.post(url, post_data, **extra_headers) + + self.assertEqual(Image.objects.count(), 0) + self.assertEqual(File.objects.count(), 0) + def test_filer_ajax_upload_file(self): self.assertEqual(Image.objects.count(), 0) folder = Folder.objects.create(name='foo') From 5990ccd16cd8b620703919cb0b6f87f6ab1b8f73 Mon Sep 17 00:00:00 2001 From: Fabian Braun Date: Tue, 19 Nov 2024 09:40:53 +0100 Subject: [PATCH 8/8] Add migration info --- README.rst | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/README.rst b/README.rst index 218660a01..c00a44c17 100644 --- a/README.rst +++ b/README.rst @@ -49,6 +49,26 @@ Documentation Please head over to the separate `documentation `_ for all the details on how to install, configure and use django-filer. +Upgrading +========= + +Version 3.3 +----------- + +django-filer version 3 contains a change in security policy for file uploads. +**By default, binary file or files of unknown type are not allowed to be uploaded.** +To allow upload of binary files in your project, add + +.. code-block:: python + + FILER_REMOVE_FILE_VALIDATORS = [ + "application/octet-stream", + ] + +to your project's settings. Be aware that binary files always are a security risk. +See the documentation for more information on how to configure file upload validators, +e.g., running files through a virus checker. + .. |pypi| image:: https://badge.fury.io/py/django-filer.svg :target: http://badge.fury.io/py/django-filer