Skip to content

Commit

Permalink
Add simple test, localize error messages
Browse files Browse the repository at this point in the history
  • Loading branch information
fsbraun committed Sep 25, 2023
1 parent 661007e commit d463838
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 11 deletions.
32 changes: 21 additions & 11 deletions filer/admin/clipboardadmin.py
Original file line number Diff line number Diff line change
Expand Up @@ -141,25 +141,35 @@ def ajax_upload(request, folder_id=None):
# the image gets attached to a folder and saved. We also
# send the error msg in the JSON and also post the message
# so that they know what is wrong with the image they uploaded
from django.contrib.messages import ERROR, add_message
pixels: int = max(1, file_obj.height) * max(1, file_obj.width)

from django.contrib.messages import ERROR, WARNING, add_message
height: int = max(1, file_obj.height)
width: int = max(1, file_obj.width)
pixels: int = width * height
aspect: float = file_obj.width / file_obj.height
res_x: int = int((FILER_MAX_IMAGE_PIXELS * aspect) ** 0.5)
res_y: int = int(res_x / aspect)
if pixels > 2 * FILER_MAX_IMAGE_PIXELS:
msg = (
f"Image size ({pixels} pixels) exceeds limit of {2 * FILER_MAX_IMAGE_PIXELS} "
"pixels, could be decompression bomb DOS attack."
)

msg = _(
"Image size (%(pixels)d pixels) exceeds limit of %(max_pixels)d "
"pixels by a factor of two or more. Resize image to (%(width)d, "
"%(height)d) resolution or lower."
).format(pixels=pixels, max_pixels=FILER_MAX_IMAGE_PIXELS,
width=res_x, height=res_y)
message = str(msg)
add_message(request, ERROR, message)
return JsonResponse({'error': message})

if pixels > FILER_MAX_IMAGE_PIXELS:
msg = f"Image size ({pixels} pixels) exceeds limit of {FILER_MAX_IMAGE_PIXELS} pixels, could be decompression bomb DOS attack."
msg = _(
"Image size (%(pixels)d pixels) exceeds limit of %(max_pixels)d "
"pixels. Consider resizing image to (%(width)d, %(height)d) resolution "
"or lower."
).format(pixels=pixels, max_pixels=FILER_MAX_IMAGE_PIXELS,
width=res_x, height=res_y)

message = str(msg)
add_message(request, ERROR, message)
return JsonResponse({'error': message})
add_message(request, WARNING, message)
# return JsonResponse({'warning': message})
file_obj.folder = folder
file_obj.save()
else:
Expand Down
23 changes: 23 additions & 0 deletions tests/test_admin.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import json
import os

import django
Expand Down Expand Up @@ -475,6 +476,28 @@ def test_filer_ajax_upload_file(self):
self.assertEqual(stored_image.original_filename, self.image_name)
self.assertEqual(stored_image.mime_type, 'image/jpeg')

def test_filer_ajax_decompression_bomb(self):
from filer.admin import clipboardadmin
DEFAULT_MAX_IMAGE_PIXELS = clipboardadmin.FILER_MAX_IMAGE_PIXELS
clipboardadmin.FILER_MAX_IMAGE_PIXELS = 800 * 200
self.assertEqual(Image.objects.count(), 0)
folder = Folder.objects.create(name='foo')
with open(self.filename, 'rb') as fh:
file_obj = django.core.files.File(fh)
url = reverse(
'admin:filer-ajax_upload',
kwargs={'folder_id': folder.pk}
) + '?filename=%s' % self.image_name
response = self.client.post(
url,
data=file_obj.read(),
content_type='image/jpeg',
**{'HTTP_X_REQUESTED_WITH': 'XMLHttpRequest'}
)
self.assertEqual(Image.objects.count(), 0)
self.assertIn("error", json.loads(response.content.decode("utf-8")))
clipboardadmin.FILER_MAX_IMAGE_PIXELS = DEFAULT_MAX_IMAGE_PIXELS

def test_filer_ajax_upload_file_using_content_type(self):
self.assertEqual(Image.objects.count(), 0)
folder = Folder.objects.create(name='foo')
Expand Down

0 comments on commit d463838

Please sign in to comment.