Skip to content

Possible double EXIF orientation handling for JPEG images during upload #194

Description

@fabiSwDevBeg

Caution

Do not file security issues in this tracker.
Send email to security@plone.org instead.
See Report a security issue.

Describe the bug

Images with EXIF Orientation (e.g. Orientation=6 / Rotate 90 CW) are already physically rotated when opened by Pillow, but plone.namedfile still applies its own EXIF-based rotation logic.
This results in inconsistent image handling and incorrect assumptions about image dimensions during upload/import.

During debugging it appears that PIL.Image.open() may already return an image with pixels rotated according to EXIF Orientation, while the EXIF metadata still reports a non-normalized orientation.
plone.namedfile then applies an additional rotation step based on EXIF, leading to double-handling or no-op rotations depending on geometry.

To Reproduce

  1. Take a JPEG image with EXIF Orientation = 6 (portrait photo stored as landscape + EXIF).
  2. Upload the image to Plone (Classic UI or Volto).
  3. Debug the image handling code in plone.namedfile, inspecting:
    • PIL.Image.open(BytesIO(data))
    • img.size
    • EXIF Orientation before any explicit rotation.
  4. Observe that:
    • img.size already reflects a portrait image.
    • EXIF Orientation is still 6.
    • plone.namedfile rotation logic is still executed.

Expected behavior

Plone should either:

  • Explicitly normalize EXIF orientation using ImageOps.exif_transpose() and then reset Orientation to 1, or
  • Detect that Pillow has already applied EXIF orientation and skip additional rotation logic.

In any case, image rotation should be applied exactly once, and image dimensions should be consistent with the applied transformation.

Screenshots

Not applicable (debug-level issue).

Software (please complete the following information):

  • OS: Linux
  • Browser: Any
  • Plone Version: 6.0.15
  • Volto Version: 17.22.3
  • Pillow 11.0.0
  • plone.namedfile 7.0.1

Additional context

A first inspection of the current code suggests that this behavior is not limited to older versions.

When debugging the upload pipeline, PIL.Image.open() loads the image using JpegImagePlugin (as expected for JPEG files) and returns an Image instance whose pixel data already appears to be rotated according to the EXIF Orientation value.

In this scenario:

  • the image geometry (img.size) already reflects the rotated image,
  • EXIF metadata still reports a non-normalized Orientation value (e.g. 6),
  • plone.namedfile then applies its own EXIF-based rotation logic.

This indicates that, at least in some Pillow versions/configurations, EXIF orientation may already be applied automatically when loading JPEG images, making the additional rotation logic in plone.namedfile redundant or incorrect.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions