Xpra: Ticket #2279: harden pillow image parsing

Apart from the obvious server-to-client transfer of window pixel data, we can receive compressed pixel data from a number of places: webcam, window icons, xdg menus, etc Some of those can flow back to the server. We should ensure that we only allow the encodings we support so that a vulnerability in another codec cannot be triggered from those code paths.

We only really care about: webp, png and jpeg for now. Those all have detectable headers.

Let's move the code to a utility function that can do the checking.

Example Image.open code that could be abused:

                from PIL import Image
                from io import BytesIO
                buf = BytesIO(icondata)
                img = Image.open(buf)
                has_alpha = img.mode=="RGBA"
                width, height = img.size
                rowstride = width * (3+int(has_alpha))
                pixbuf = get_pixbuf_from_data(img.tobytes(), has_alpha, width, height, rowstride)


Sun, 21 Apr 2019 05:31:30 GMT - Antoine Martin: status, description changed


Sun, 21 Apr 2019 06:51:08 GMT - Antoine Martin:

Here's a list of the formats supported by Image File Formats (long!).

Work started in r22493: we filter tray icons and window icons (server to client), dbus and win32 notifiers only accept png (now actually enforced), webcam validates the encodings used. r22494 also removes support for jpeg2000 (#618) - that encoding was pretty useless anyway.

Still TODO:


Tue, 23 Apr 2019 08:07:48 GMT - Antoine Martin: status changed; resolution set

Work completed in:

To test, we have to build --without-webp and --without-jpeg_decoder otherwise those faster cython decoders have precedence (and they don't need validating since they only decode the one format they are designed for). Then just attach with --encodings=jpeg (or --encodings=png.


Fri, 10 Jan 2020 17:55:18 GMT - Antoine Martin:

r22493 caused a regression with pngP and png/L, fixed in r24936.


Sat, 23 Jan 2021 05:46:58 GMT - migration script:

this ticket has been moved to: https://github.com/Xpra-org/xpra/issues/2279