Verified Commit a7d77565 authored by Eliot Berriot's avatar Eliot Berriot
Browse files

Fix #374: Strip EXIF metadata from uploaded avatars to avoid leaking private data

parent ddeb1a66
import collections
import io
import PIL
import os
from rest_framework import serializers
from django.core.exceptions import ObjectDoesNotExist
from django.core.files.uploadedfile import SimpleUploadedFile
from django.utils.encoding import smart_text
from django.utils.translation import ugettext_lazy as _
......@@ -190,3 +194,25 @@ def track_fields_for_update(*fields):
return serializer_class
return decorator
class StripExifImageField(serializers.ImageField):
def to_internal_value(self, data):
file_obj = super().to_internal_value(data)
image =
data = list(image.getdata())
image_without_exif =, image.size)
with io.BytesIO() as output:
content = output.getvalue()
return SimpleUploadedFile(, content, content_type=file_obj.content_type
......@@ -11,7 +11,7 @@ from rest_framework import serializers
from versatileimagefield.serializers import VersatileImageFieldSerializer
from funkwhale_api.activity import serializers as activity_serializers
from funkwhale_api.common import serializers as common_serializers
from . import models
......@@ -66,7 +66,13 @@ class UserActivitySerializer(activity_serializers.ModelSerializer):
return "Person"
avatar_field = VersatileImageFieldSerializer(allow_null=True, sizes="square")
class AvatarField(
common_serializers.StripExifImageField, VersatileImageFieldSerializer
avatar_field = AvatarField(allow_null=True, sizes="square")
class UserBasicSerializer(serializers.ModelSerializer):
import os
import PIL
from django.core.files.uploadedfile import SimpleUploadedFile
import django_filters
from funkwhale_api.common import serializers
......@@ -163,3 +168,17 @@ def test_track_fields_for_update(mocker):
{"field1": "value1", "field2": "value2"},
{"field1": "newvalue1", "field2": "newvalue2"},
def test_strip_exif_field():
source_path = os.path.join(os.path.dirname(__file__), "exif.jpg")
source =
assert bool(source._getexif())
with open(source_path, "rb") as f:
uploaded = SimpleUploadedFile("source.jpg",, content_type="image/jpeg")
field = serializers.StripExifImageField()
cleaned =
assert cleaned._getexif() is None
Strip EXIF metadata from uploaded avatars to avoid leaking private data (#374)
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment