Skip to main content
CVE Vulnerability Database
Vulnerability Database/CVE-2024-49769

CVE-2024-49769: Agendaless Waitress DOS Vulnerability

CVE-2024-49769 is a denial of service vulnerability in Agendaless Waitress that allows attackers to exhaust sockets through a race condition. This post covers technical details, affected versions, impact, and mitigation.

Published:

CVE-2024-49769 Overview

CVE-2024-49769 affects Waitress, a Web Server Gateway Interface (WSGI) server for Python 2 and 3. The vulnerability stems from a race condition in connection handling. When a remote client closes the connection before Waitress calls getpeername(), the server fails to clean up the connection properly. The main thread then attempts to write to a socket that no longer exists, while the socket remains in the processing list. This creates a busy-loop on the write function, allowing a remote attacker to exhaust available sockets with minimal resources. Waitress 3.0.1 contains the fix that removes the race condition.

Critical Impact

Unauthenticated remote attackers can exhaust server socket resources with minimal effort, causing denial of service against any application served by vulnerable Waitress versions.

Affected Products

  • Agendaless Waitress versions prior to 3.0.1
  • Python applications using Waitress as their WSGI server
  • Debian LTS distributions packaging vulnerable Waitress releases

Discovery Timeline

  • 2024-10-29 - CVE-2024-49769 published to the National Vulnerability Database (NVD)
  • 2024-11-21 - Last updated in NVD database

Technical Details for CVE-2024-49769

Vulnerability Analysis

The flaw is classified as [CWE-772] Missing Release of Resource after Effective Lifetime. Waitress uses an asynchronous dispatcher derived from wasyncore to manage client sockets. During channel initialization, the dispatcher calls sock.getpeername() to record the remote address. If the remote peer closes the TCP connection in the small window before this call, the socket transitions to an invalid state.

The original code marked the channel as connected = True before resolving the peer name, then caught ENOTCONN or EINVAL errors by setting connected = False. However, the socket reference remained in the dispatcher's socket map. The main event loop continued to select the channel for writes, repeatedly invoking the write handler on a dead socket. This produces a tight CPU-bound loop and prevents the channel from being released.

Root Cause

The race condition occurs between socket acceptance and peer name resolution in src/waitress/wasyncore.py. The cleanup path on getpeername() failure did not remove the channel from the active processing list, leaving orphaned sockets that consumed file descriptors and CPU time.

Attack Vector

A remote attacker opens TCP connections to the Waitress listener and closes them immediately, before the server completes channel setup. Each successful race leaks a socket entry and adds CPU load to the main thread. Because the attack requires no authentication and only minimal bandwidth, an attacker can rapidly exhaust the server's available file descriptors.

python
# Patched code in src/waitress/wasyncore.py
# get a socket from a blocking source.
sock.setblocking(0)
self.set_socket(sock, map)
# Removed: self.connected = True and getpeername() block
# that previously created the race condition
else:
    self.socket = None

Source: Pylons/waitress commit 1ae4e89

python
# Patched code in src/waitress/channel.py
self.outbuf_lock = threading.Condition()

wasyncore.dispatcher.__init__(self, sock, map=map)
self.connected = True
self.addr = addr
self.requests = []

Source: Pylons/waitress commit 1ae4e89

The patch moves the connected = True assignment and address handling into HTTPChannel.__init__, removing the getpeername() call that triggered the race.

Detection Methods for CVE-2024-49769

Indicators of Compromise

  • Sustained high CPU usage by the Waitress process without corresponding request throughput
  • Growing file descriptor counts on the server process that do not decrease over time
  • Large numbers of short-lived TCP connections from the same source IP closed in FIN_WAIT or CLOSE_WAIT states
  • Application logs showing channels stuck without completing request processing

Detection Strategies

  • Monitor the waitress process for unusual epoll or select wake-up rates indicating busy-loop behavior
  • Track open socket counts via lsof or /proc/<pid>/fd and alert on monotonic growth
  • Inspect netstat output for abnormal volumes of half-closed connections targeting the Waitress listener port
  • Compare installed Waitress versions against 3.0.1 using software inventory tooling

Monitoring Recommendations

  • Configure alerts on Python WSGI process CPU exceeding baseline thresholds for sustained periods
  • Log and rate-limit clients that open and immediately close TCP connections to the WSGI listener
  • Use reverse proxy access logs (nginx, HAProxy) to identify abnormal connection churn upstream of Waitress
  • Forward host telemetry to a centralized log platform to correlate file descriptor exhaustion with network patterns

How to Mitigate CVE-2024-49769

Immediate Actions Required

  • Upgrade Waitress to version 3.0.1 or later across all production and development environments
  • Apply distribution-provided patches such as the Debian LTS update referenced in the advisory
  • Audit Python environments using pip list or SBOM tooling to locate vulnerable waitress installations
  • Place Waitress behind a hardened reverse proxy that can absorb abusive connection patterns

Patch Information

The fix is delivered in Waitress 3.0.1 via pull request #435 and commit 1ae4e894c9f76543bee06584001583fc6fa8c95c. Refer to the GHSA-3f84-rpwh-47g6 advisory for full details and the Debian LTS announcement for distribution packages.

Workarounds

  • Front Waitress with nginx, HAProxy, or a CDN that terminates TCP connections and forwards only established requests
  • Apply connection rate limits and concurrent connection caps at the firewall or load balancer layer
  • Restrict direct internet exposure of Waitress listeners until the patched version is deployed
bash
# Upgrade Waitress to the patched release
pip install --upgrade 'waitress>=3.0.1'

# Verify installed version
python -c "import waitress; print(waitress.__version__)"

Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

Default Legacy - Prefooter | Experience the World’s Most Advanced Cybersecurity Platform

Experience the Most Advanced Cybersecurity Platform

See how the world’s most intelligent, autonomous cybersecurity platform can protect your organization today and into the future.