CVE-2024-12254
High · 7.5CVSS
7.5
EPSS
1.9%
Published
Dec 6, 2024
CISA due date
—
Cloudanix analysis
A bug in certain Python networking code can cause programs to use up all available memory and stop working when handling specific data patterns.
- Exploitation
- Remote Unauthenticated
- Attacker needs
- None
- Complexity
- Low
- Impact
- Denial Of Service
- Component
- Library
- Class
- Denial of service
- Remediation
- Upgrade
- Effort
- Medium
- Patch risk
- Low
What it actually does
The asyncio._SelectorSocketTransport.writelines() method in Python 3.12.0 and later fails to enforce backpressure by pausing writes and signaling the protocol to drain when the write buffer reaches the high-water mark, allowing unbounded buffer growth and eventual memory exhaustion on macOS and Linux.
Why it matters to the business
Affected async Python network applications may experience sudden memory exhaustion leading to service crashes or degraded performance, though impact is limited to a small subset of users relying on specific asyncio protocol and writelines patterns.
How an attack unfolds
An attacker interacts with a vulnerable Python asyncio-based server or client that uses protocols and the writelines method, sending traffic that repeatedly triggers writes without buffer draining, gradually consuming memory until the process terminates or becomes unresponsive.
How to fix it
Upgrade python/cpython to the fixed commit 71e8429ac8e2adc10084ab5ec29a62f4b6671a82 or later releases that restore proper backpressure behavior in _SelectorSocketTransport.writelines().
How to confirm the fix worked
Confirm the installed Python version is 3.12.0 or later, apply the referenced commit or subsequent release, and test that writelines pauses and signals drain at the high-water mark under load.
Typical attack path
- Identify a target application using Python 3.12+ asyncio protocols with writelines on macOS or Linux
- Establish a network connection to the affected transport
- Send crafted or high-volume data that exercises writelines repeatedly
- Observe continued buffer growth without high-water mark enforcement
- Drive memory consumption until exhaustion and denial of service
How to detect it
Monitor for sudden or sustained increases in memory usage by Python processes using asyncio on macOS or Linux; review application logs for repeated writelines calls without corresponding drain events; correlate with network traffic volumes on affected services.
What your security team should do
- Identify and inventory Python 3.12+ deployments using asyncio protocols and writelines
- Prioritize upgrade to the fixed commit in development, staging, and production environments
- Monitor memory usage of asyncio-based services for anomalous growth patterns
- Review application code for reliance on writelines with custom protocols
The record
Starting in Python 3.12.0, the asyncio._SelectorSocketTransport.writelines() method would not "pause" writing and signal to the Protocol to drain the buffer to the wire once the write buffer reached the "high-water mark". Because of this, Protocols would not periodically drain the write buffer potentially leading to memory exhaustion. This vulnerability likely impacts a small number of users, you must be using Python 3.12.0 or later, on macOS or Linux, using the asyncio module with protocols, and using .writelines() method which had new zero-copy-on-write behavior in Python 3.12.0 and later. If not all of these factors are true then your usage of Python is unaffected.
Affected packages
| Ecosystem | Package | Introduced | Fixed |
|---|---|---|---|
| AlmaLinux:8 | python3.12 | 0 | 3.12.8-1.el8_10 |
| AlmaLinux:8 | python3.12-debug | 0 | 3.12.8-1.el8_10 |
| AlmaLinux:8 | python3.12-devel | 0 | 3.12.8-1.el8_10 |
| AlmaLinux:8 | python3.12-idle | 0 | 3.12.8-1.el8_10 |
| AlmaLinux:8 | python3.12-libs | 0 | 3.12.8-1.el8_10 |
| AlmaLinux:8 | python3.12-rpm-macros | 0 | 3.12.8-1.el8_10 |
| AlmaLinux:8 | python3.12-test | 0 | 3.12.8-1.el8_10 |
| AlmaLinux:8 | python3.12-tkinter | 0 | 3.12.8-1.el8_10 |
| AlmaLinux:9 | python3.12 | 0 | 3.12.5-2.el9_5.2 |
| AlmaLinux:9 | python3.12-debug | 0 | 3.12.5-2.el9_5.2 |
| AlmaLinux:9 | python3.12-devel | 0 | 3.12.5-2.el9_5.2 |
| AlmaLinux:9 | python3.12-idle | 0 | 3.12.5-2.el9_5.2 |
| AlmaLinux:9 | python3.12-libs | 0 | 3.12.5-2.el9_5.2 |
| AlmaLinux:9 | python3.12-test | 0 | 3.12.5-2.el9_5.2 |
| AlmaLinux:9 | python3.12-tkinter | 0 | 3.12.5-2.el9_5.2 |
| Alpine:v3.20 | python3 | 0 | 3.12.8-r1 |
| Alpine:v3.21 | python3 | 0 | 3.12.8-r1 |
| Alpine:v3.22 | python3 | 0 | 3.12.8-r1 |
| Bitnami | libpython | 3.12.0 | 3.12.9 |
| Bitnami | python | 3.12.0 | No fix |
| Bitnami | python | 3.12.0 | 3.12.9 |
| Bitnami | python-min | 3.12.0 | No fix |
| Bitnami | python-min | 3.12.0 | 3.12.9 |
| Chainguard | python-3.12 | 0 | 3.12.8-r1 |
| Chainguard | python-3.12-base | 0 | 3.12.8-r1 |
| Chainguard | python-3.12-base-dev | 0 | 3.12.8-r1 |
| Chainguard | python-3.12-dev | 0 | 3.12.8-r1 |
| Chainguard | python-3.12-doc | 0 | 3.12.8-r1 |
| Chainguard | python-3.12-privileged-netbindservice | 0 | 3.12.8-r1 |
| Chainguard | python-3.12-tk | 0 | 3.12.8-r1 |
| Chainguard | python-3.13 | 0 | 3.13.1-r1 |
| Chainguard | python-3.13-base | 0 | 3.13.1-r1 |
| Chainguard | python-3.13-base-dev | 0 | 3.13.1-r1 |
| Chainguard | python-3.13-dev | 0 | 3.13.1-r1 |
| Chainguard | python-3.13-doc | 0 | 3.13.1-r1 |
| Chainguard | python-3.13-privileged-netbindservice | 0 | 3.13.1-r1 |
| Chainguard | python-3.13-tk | 0 | 3.13.1-r1 |
| Debian:13 | python3.12 | 0 | 3.12.8-2 |
| Debian:13 | python3.13 | 0 | 3.13.1-2 |
| Debian:14 | python3.13 | 0 | 3.13.1-2 |
| Red Hat:enterprise_linux:8::appstream | python3.12 | 0 | 0:3.12.8-1.el8_10 |
| Red Hat:enterprise_linux:8::appstream | python3.12-debug | 0 | 0:3.12.8-1.el8_10 |
| Red Hat:enterprise_linux:8::appstream | python3.12-debuginfo | 0 | 0:3.12.8-1.el8_10 |
| Red Hat:enterprise_linux:8::appstream | python3.12-debugsource | 0 | 0:3.12.8-1.el8_10 |
| Red Hat:enterprise_linux:8::appstream | python3.12-devel | 0 | 0:3.12.8-1.el8_10 |
| Red Hat:enterprise_linux:8::appstream | python3.12-idle | 0 | 0:3.12.8-1.el8_10 |
| Red Hat:enterprise_linux:8::appstream | python3.12-libs | 0 | 0:3.12.8-1.el8_10 |
| Red Hat:enterprise_linux:8::appstream | python3.12-rpm-macros | 0 | 0:3.12.8-1.el8_10 |
| Red Hat:enterprise_linux:8::appstream | python3.12-test | 0 | 0:3.12.8-1.el8_10 |
| Red Hat:enterprise_linux:8::appstream | python3.12-tkinter | 0 | 0:3.12.8-1.el8_10 |
| Red Hat:enterprise_linux:8::crb | python3.12 | 0 | 0:3.12.8-1.el8_10 |
| Red Hat:enterprise_linux:8::crb | python3.12-debug | 0 | 0:3.12.8-1.el8_10 |
| Red Hat:enterprise_linux:8::crb | python3.12-debuginfo | 0 | 0:3.12.8-1.el8_10 |
| Red Hat:enterprise_linux:8::crb | python3.12-debugsource | 0 | 0:3.12.8-1.el8_10 |
| Red Hat:enterprise_linux:8::crb | python3.12-devel | 0 | 0:3.12.8-1.el8_10 |
| Red Hat:enterprise_linux:8::crb | python3.12-idle | 0 | 0:3.12.8-1.el8_10 |
| Red Hat:enterprise_linux:8::crb | python3.12-libs | 0 | 0:3.12.8-1.el8_10 |
| Red Hat:enterprise_linux:8::crb | python3.12-rpm-macros | 0 | 0:3.12.8-1.el8_10 |
| Red Hat:enterprise_linux:8::crb | python3.12-test | 0 | 0:3.12.8-1.el8_10 |
| Red Hat:enterprise_linux:8::crb | python3.12-tkinter | 0 | 0:3.12.8-1.el8_10 |
| Red Hat:enterprise_linux:9::appstream | python3.12 | 0 | 0:3.12.5-2.el9_5.2 |
| Red Hat:enterprise_linux:9::appstream | python3.12-debug | 0 | 0:3.12.5-2.el9_5.2 |
| Red Hat:enterprise_linux:9::appstream | python3.12-debuginfo | 0 | 0:3.12.5-2.el9_5.2 |
| Red Hat:enterprise_linux:9::appstream | python3.12-debugsource | 0 | 0:3.12.5-2.el9_5.2 |
| Red Hat:enterprise_linux:9::appstream | python3.12-devel | 0 | 0:3.12.5-2.el9_5.2 |
| Red Hat:enterprise_linux:9::appstream | python3.12-idle | 0 | 0:3.12.5-2.el9_5.2 |
| Red Hat:enterprise_linux:9::appstream | python3.12-libs | 0 | 0:3.12.5-2.el9_5.2 |
| Red Hat:enterprise_linux:9::appstream | python3.12-test | 0 | 0:3.12.5-2.el9_5.2 |
| Red Hat:enterprise_linux:9::appstream | python3.12-tkinter | 0 | 0:3.12.5-2.el9_5.2 |
| Red Hat:enterprise_linux:9::crb | python3.12 | 0 | 0:3.12.5-2.el9_5.2 |
| Red Hat:enterprise_linux:9::crb | python3.12-debug | 0 | 0:3.12.5-2.el9_5.2 |
| Red Hat:enterprise_linux:9::crb | python3.12-debuginfo | 0 | 0:3.12.5-2.el9_5.2 |
| Red Hat:enterprise_linux:9::crb | python3.12-debugsource | 0 | 0:3.12.5-2.el9_5.2 |
| Red Hat:enterprise_linux:9::crb | python3.12-devel | 0 | 0:3.12.5-2.el9_5.2 |
| Red Hat:enterprise_linux:9::crb | python3.12-idle | 0 | 0:3.12.5-2.el9_5.2 |
| Red Hat:enterprise_linux:9::crb | python3.12-libs | 0 | 0:3.12.5-2.el9_5.2 |
| Red Hat:enterprise_linux:9::crb | python3.12-test | 0 | 0:3.12.5-2.el9_5.2 |
| Red Hat:enterprise_linux:9::crb | python3.12-tkinter | 0 | 0:3.12.5-2.el9_5.2 |
| Red Hat:rhel_eus:9.4::appstream | python3.12 | 0 | 0:3.12.1-4.el9_4.5 |
| Red Hat:rhel_eus:9.4::appstream | python3.12-debug | 0 | 0:3.12.1-4.el9_4.5 |
| Red Hat:rhel_eus:9.4::appstream | python3.12-debuginfo | 0 | 0:3.12.1-4.el9_4.5 |
| Red Hat:rhel_eus:9.4::appstream | python3.12-debugsource | 0 | 0:3.12.1-4.el9_4.5 |
| Red Hat:rhel_eus:9.4::appstream | python3.12-devel | 0 | 0:3.12.1-4.el9_4.5 |
| Red Hat:rhel_eus:9.4::appstream | python3.12-idle | 0 | 0:3.12.1-4.el9_4.5 |
| Red Hat:rhel_eus:9.4::appstream | python3.12-libs | 0 | 0:3.12.1-4.el9_4.5 |
| Red Hat:rhel_eus:9.4::appstream | python3.12-test | 0 | 0:3.12.1-4.el9_4.5 |
| Red Hat:rhel_eus:9.4::appstream | python3.12-tkinter | 0 | 0:3.12.1-4.el9_4.5 |
| Red Hat:rhel_eus:9.4::crb | python3.12 | 0 | 0:3.12.1-4.el9_4.5 |
| Red Hat:rhel_eus:9.4::crb | python3.12-debug | 0 | 0:3.12.1-4.el9_4.5 |
| Red Hat:rhel_eus:9.4::crb | python3.12-debuginfo | 0 | 0:3.12.1-4.el9_4.5 |
| Red Hat:rhel_eus:9.4::crb | python3.12-debugsource | 0 | 0:3.12.1-4.el9_4.5 |
| Red Hat:rhel_eus:9.4::crb | python3.12-devel | 0 | 0:3.12.1-4.el9_4.5 |
| Red Hat:rhel_eus:9.4::crb | python3.12-idle | 0 | 0:3.12.1-4.el9_4.5 |
| Red Hat:rhel_eus:9.4::crb | python3.12-libs | 0 | 0:3.12.1-4.el9_4.5 |
| Red Hat:rhel_eus:9.4::crb | python3.12-test | 0 | 0:3.12.1-4.el9_4.5 |
| Red Hat:rhel_eus:9.4::crb | python3.12-tkinter | 0 | 0:3.12.1-4.el9_4.5 |
| Rocky Linux:8 | python3.12 | 0 | 0:3.12.8-1.el8_10 |
| Rocky Linux:9 | python3.12 | 0 | 0:3.12.5-2.el9_5.2 |
| SUSE:Linux Enterprise Module for Python 3 15 SP6 | python312 | 0 | 3.12.8-150600.3.12.1 |
| SUSE:Linux Enterprise Module for Python 3 15 SP6 | python312 | 0 | 3.12.9-150600.3.18.1 |
| SUSE:Linux Enterprise Module for Python 3 15 SP6 | python312-core | 0 | 3.12.8-150600.3.12.1 |
| SUSE:Linux Enterprise Module for Python 3 15 SP6 | python312-core | 0 | 3.12.9-150600.3.18.1 |
| SUSE:Linux Enterprise Module for Python 3 15 SP7 | python313 | 0 | 3.13.5-150700.4.11.1 |
| SUSE:Linux Enterprise Module for Python 3 15 SP7 | python313-core | 0 | 3.13.5-150700.4.11.1 |
| Ubuntu:24.04:LTS | python3.12 | 0 | 3.12.3-1ubuntu0.4 |
| Ubuntu:24.10 | python3.12 | 0 | 3.12.7-1ubuntu1.1 |
| Ubuntu:24.10 | python3.13 | 0 | No fix |
| Ubuntu:25.10 | python3.12 | 0 | No fix |
| Wolfi | python-3.12 | 0 | 3.12.8-r1 |
| Wolfi | python-3.12-base | 0 | 3.12.8-r1 |
| Wolfi | python-3.12-base-dev | 0 | 3.12.8-r1 |
| Wolfi | python-3.12-dev | 0 | 3.12.8-r1 |
| Wolfi | python-3.12-doc | 0 | 3.12.8-r1 |
| Wolfi | python-3.12-privileged-netbindservice | 0 | 3.12.8-r1 |
| Wolfi | python-3.12-tk | 0 | 3.12.8-r1 |
| Wolfi | python-3.13 | 0 | 3.13.1-r1 |
| Wolfi | python-3.13-base | 0 | 3.13.1-r1 |
| Wolfi | python-3.13-base-dev | 0 | 3.13.1-r1 |
| Wolfi | python-3.13-dev | 0 | 3.13.1-r1 |
| Wolfi | python-3.13-doc | 0 | 3.13.1-r1 |
| Wolfi | python-3.13-privileged-netbindservice | 0 | 3.13.1-r1 |
| Wolfi | python-3.13-tk | 0 | 3.13.1-r1 |
| openSUSE:Leap 15.6 | python312 | 0 | 3.12.8-150600.3.12.1 |
| openSUSE:Leap 15.6 | python312 | 0 | 3.12.9-150600.3.18.1 |
| openSUSE:Leap 15.6 | python312-core | 0 | 3.12.8-150600.3.12.1 |
| openSUSE:Leap 15.6 | python312-core | 0 | 3.12.9-150600.3.18.1 |
| openSUSE:Leap 15.6 | python312-documentation | 0 | 3.12.8-150600.3.12.1 |
| openSUSE:Leap 15.6 | python312-documentation | 0 | 3.12.9-150600.3.18.1 |
| openSUSE:Tumbleweed | python-aiohttp | 0 | 3.11.16-1.1 |
| openSUSE:Tumbleweed | python312 | 0 | 3.12.8-1.1 |
| openSUSE:Tumbleweed | python313 | 0 | 3.13.1-1.1 |
Related vulnerabilities
- CVE-2025-12084 When building nested elements using xml.dom.minidom methods such as appendChild() that… Also affects python3.12
- CVE-2025-8291 The 'zipfile' module would not check the validity of the ZIP64 End of Central Directory… Also affects python3.12
- CVE-2025-8194 There is a defect in the CPython “tarfile” module affecting the “TarFile” extraction and… Also affects python3.12
- CVE-2024-12718 Allows modifying some file metadata (e.g. Also affects python3.12
- CVE-2025-4517 Allows arbitrary filesystem writes outside the extraction directory during extraction… Also affects python3.12
- CVE-2025-4138 Allows the extraction filter to be ignored, allowing symlink targets to point outside the… Also affects python3.12
- CVE-2025-4330 Allows the extraction filter to be ignored, allowing symlink targets to point outside the… Also affects python3.12
- CVE-2025-4435 When using a TarFile.errorlevel = 0 and extracting with a filter the documented behavior… Also affects python3.12