CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



CVE-2026-64847

CVE-2026-64847: Indefinite Denial of Service via Undrained Stderr in AnyIO Process Pool Workers

Amit Schendel
Amit Schendel
Senior Security Researcher

Sep 19, 2026·6 min read·5 visits

Executive Summary (TL;DR)

AnyIO process-pool workers can block indefinitely when writing to undrained stderr streams, causing a permanent deadlock of the calling event loop.

A denial-of-service vulnerability exists in AnyIO prior to version 4.14.2. Standard error streams of process-pool workers are connected to an operating system pipe that is never drained by the parent process. This allows a worker to fill the pipe buffer and deadlock indefinitely.

Vulnerability Overview

AnyIO is an asynchronous concurrency framework for Python that abstracts compatibility over either Trio or asyncio. The framework provides utility interfaces to run synchronous execution units inside process pools using the to_process.run_sync() method. This abstraction coordinates execution by establishing inter-process communication (IPC) channels between the parent event loop and the spawned worker process.

During normal operation, the parent process monitors standard streams to read execution outcomes and serialize protocol inputs. The vulnerability, designated as CVE-2026-64847, lies in the handling of the standard error stream (sys.stderr) inside the worker processes. Although standard streams are documented to be safely isolated, standard error is left connected to a parent-owned operating system pipe.

Because the parent process does not active read or drain the standard error pipe during worker execution, any output routed to stderr persists in the pipe's internal kernel buffer. This lack of resource drainage introduces an immediate vulnerability where standard tracebacks, debug logging, or third-party print statements can fill the kernel buffer and stall execution.

Root Cause Analysis

The underlying vulnerability represents a failure to throttle or drain allocated operating system pipe buffers, classified as CWE-770. On modern kernel architectures, inter-process communication pipes employ finite ring buffers managed directly by the kernel. Under standard Linux configurations, this pipe buffer size defaults to 64 KiB (65,536 bytes), while Windows systems dynamically allocate similarly constrained resources.

When a child process outputs data to a standard pipe, the kernel buffers the payload until the parent process executes a read system call. If the child process writes a volume of data exceeding the buffer capacity, and the parent process is not actively draining the pipe, the operating system kernel blocks the writing thread. The writer process transitions into an uninterruptible sleep state waiting for buffer clearance.

In AnyIO versions prior to 4.14.2, the parent process awaits execution results from standard output (sys.stdout) while ignoring standard error (sys.stderr). If the worker process generates more than 64 KiB of diagnostic data on stderr, the write calls block. Consequently, the worker process stalls midway, and the parent process blocks indefinitely waiting for the worker to finish, creating a permanent deadlock.

Process Interaction Flow

The sequential flow of the deadlock condition highlights the blockages occurring on both sides of the inter-process pipe.

As the diagram demonstrates, the deadlock state cannot resolve itself because neither process can advance. The worker process cannot complete its execution loop to write a success token to the stdout pipe, and the parent process does not read from the stderr pipe that is blocking the worker.

Code-Level Analysis

The bug resides in process_worker() located within src/anyio/to_process.py. In affected versions of AnyIO, the worker initialization routine actively redirects standard input and standard output to null devices to avoid protocol pollution but leaves standard error unhandled.

# Vulnerable Implementation (Pre-4.14.2)
def process_worker() -> None:
    stdout = sys.stdout
    sys.stdin = open(os.devnull)
    sys.stdout = open(os.devnull, "w")
    # sys.stderr is completely omitted and remains connected to the parent pipe!
 
    stdout.buffer.write(b"READY\n")
    while True:
        # Worker loop waiting for payload

To remediate the vulnerability, the standard error stream must be redirected to os.devnull alongside the standard output stream. The fix merged in commit f1b7301c8264b0d2e8d24a5788fd29e93dea4040 implements this behavior:

# Patched Implementation (4.14.2)
def process_worker() -> None:
    stdout = sys.stdout
    sys.stdin = open(os.devnull)
    sys.stdout = open(os.devnull, "w")
    sys.stderr = open(os.devnull, "w") # Safe redirection of standard error
 
    stdout.buffer.write(b"READY\n")
    while True:
        # Worker loop waiting for payload

With this single-line modification, any diagnostic messages, warnings, or debug statements emitted during execution are discarded by the kernel, preventing pipe buffer saturation.

Exploitation Methodology

Exploiting this deadlock requires the ability to influence input parsed by the process pool worker, causing it to write verbose output to the standard error stream. This threat model is common in systems executing user-submitted scripts or parsing malicious inputs that trigger expansive logging or tracebacks.

An attacker can trigger the vulnerability by supplying input that forces deep recursive errors, validation warning logs, or direct diagnostic dumps. In configurations allowing untrusted code execution, a simple script writing directly to sys.stderr is sufficient to fill the 64 KiB buffer.

A typical proof-of-concept payload targeting vulnerable implementations is structured as follows:

import anyio
import sys
from anyio import to_process
 
def malicious_worker():
    # Generate a payload larger than the 64 KiB OS pipe buffer
    payload = "X" * (100 * 1024)
    sys.stderr.write(payload)
    sys.stderr.flush() # This call blocks indefinitely under AnyIO < 4.14.2
    return "success"
 
async def main():
    print("[*] Dispatching process pool worker...")
    # The execution will freeze indefinitely here without timeout configuration
    await to_process.run_sync(malicious_worker)
 
if __name__ == "__main__":
    anyio.run(main)

When executed on a vulnerable system, the parent process remains blocked indefinitely during the run_sync call.

Impact Assessment

The security impact of CVE-2026-64847 is focused exclusively on the availability of the target system, carrying a CVSS score of 6.8. Successful exploitation results in a persistent denial-of-service condition affecting the application pool.

Because AnyIO is a foundational library for high-throughput asynchronous applications, a single blocked worker process can rapidly consume available worker slots in the application process pool. Once the process pool is exhausted, any subsequent requests requiring subprocess isolation will hang, causing wider application degradation.

The attack vector is local (AV:L), meaning the attacker must be capable of executing code or triggering input-driven errors within the worker context. The vulnerability does not present potential for privilege escalation, confidentiality loss, or integrity compromise.

Remediation and Mitigation

The recommended remediation path is upgrading the AnyIO installation to version 4.14.2 or newer, which completely closes the vulnerable code path by redirecting worker sys.stderr streams.

If upgrading is not immediately possible, developers can implement programmatic mitigation within the synchronous execution unit itself. Manually redirecting sys.stderr to a null target during task startup ensures safety:

import os
import sys
 
def safe_worker_context():
    original_stderr = sys.stderr
    sys.stderr = open(os.devnull, "w")
    try:
        # Execute standard application logic here
        pass
    finally:
        sys.stderr.close()
        sys.stderr = original_stderr

Additionally, defense-in-depth measures should include enforcing strict timeouts using anyio.fail_after() when waiting on process pool tasks to prevent infinite application hangs.

Fix Analysis (1)

Technical Appendix

CVSS Score
6.8/ 10
CVSS:4.0/AV:L/AC:L/AT:N/PR:L/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N

Affected Systems

AnyIO Python asynchronous concurrency framework

Affected Versions Detail

Product
Affected Versions
Fixed Version
anyio
agronholm
< 4.14.24.14.2
AttributeDetail
CWE IDCWE-770
Attack VectorLocal (AV:L)
CVSS Score6.8 (Medium)
EPSS ScoreNot currently indexed
ImpactHigh Availability Impact (Denial of Service)
Exploit StatusPoC
KEV StatusNot listed in CISA KEV

MITRE ATT&CK Mapping

T1499Endpoint Denial of Service
Impact
CWE-770
Allocation of Resources Without Limits or Throttling

The software allocates a finite resource without imposing limits or implementing proper mechanisms to drain, restrict, or throttle consumption, leading to a permanent depletion of that resource (deadlock/hang).

Known Exploits & Detection

GitHub Advisory / Official Regression TestProof of concept demonstrating worker deadlock by flooding standard error with large data buffers.

References & Sources

  • [1]GitHub Security Advisory GHSA-5p39-cfhj-2xmp
  • [2]AnyIO Pull Request #1207
  • [3]AnyIO Patch Commit f1b7301
  • [4]NVD - CVE-2026-64847
  • [5]Wiz Vulnerability Database Details

Attack Flow Diagram

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.

More Reports

•32 minutes ago•CVE-2026-63405
5.9

CVE-2026-63405: Insufficient Verification of Data Authenticity in AnyCable Pusher REST API

AnyCable is a real-time communication server. Prior to version 1.6.15, its Pusher-compatible REST API suffered from an authentication bypass vulnerability because it failed to verify that the request body matched the signature-validated body_md5 parameter. This allows attackers to perform replay attacks with modified body contents.

Amit Schendel
Amit Schendel
2 views•5 min read
•about 3 hours ago•CVE-2026-63349
7.0

CVE-2026-63349: Privilege Dropping Bypass and Denial of Service in AnyIO Subprocess Module

CVE-2026-63349 is a critical privilege-dropping bypass vulnerability in the AnyIO asynchronous framework (versions 4.14.0 and 4.14.1) on POSIX platforms. Due to a variable assignment typo, supplementary groups specified by the developer are not correctly propagated to the execution backend, resulting in subprocesses retaining the parent process's elevated supplementary group permissions.

Alon Barad
Alon Barad
7 views•5 min read
•about 4 hours ago•CVE-2026-63406
5.9

CVE-2026-63406: Information Disclosure via Insecure Telemetry and Hardcoded Credentials in AnyCable-Go

CVE-2026-63406 is an information disclosure vulnerability in AnyCable-go prior to version 1.6.15. The built-in telemetry client is enabled by default with a hardcoded public authentication token ('secret'). This client digests highly sensitive configuration parameters and command-line arguments, including JWT secrets and RPC secrets, into a stable SHA-256 fingerprint. This fingerprint is sent over public networks, exposing those administrative secrets to offline dictionary and brute-force attacks if intercepted.

Alon Barad
Alon Barad
5 views•5 min read
•about 5 hours ago•CVE-2026-84992
6.1

CVE-2026-84992: Cross-Site Scripting (XSS) via Fenced Code Block Parsing in md-editor-v3

CVE-2026-84992 is a Cross-Site Scripting (XSS) vulnerability affecting md-editor-v3 before version 6.5.4. It occurs because the fenced-code block language parser directly interpolates unescaped language metadata into unquoted HTML attributes inside the custom rendering callback. This bypasses the built-in XSSPlugin which runs during the parsing phase, before rendering.

Amit Schendel
Amit Schendel
8 views•6 min read
•about 6 hours ago•CVE-2026-81505
7.1

CVE-2026-81505: Broken Object Level Authorization (BOLA) in Convoy Webhook Source Retrieval

CVE-2026-81505 is a high-severity Broken Object Level Authorization (BOLA) / Insecure Direct Object Reference (IDOR) vulnerability in Convoy, a cloud-native webhooks gateway. In affected versions prior to 26.6.8, the single-item Source retrieval API endpoint authorizes project access but fails to confirm if the requested Source belongs to that specific project. This logical flaw allows authenticated users or project-scoped API key holders to bypass tenant isolation boundaries and retrieve unredacted, plaintext message broker credentials for Apache Kafka, Amazon SQS, RabbitMQ, and Google Cloud Pub/Sub belonging to other tenants. This issue is fully patched in version 26.6.8.

Amit Schendel
Amit Schendel
9 views•5 min read
•about 7 hours ago•CVE-2026-77339
5.1

CVE-2026-77339: Unauthenticated Remote Command Execution in Process Compose via DNS Rebinding

CVE-2026-77339 is a critical security vulnerability in Process Compose before version 1.120.0. The Model Context Protocol (MCP) Server-Sent Events (SSE) listener transport subsystem fails to validate the HTTP Host and Origin headers, and does not enforce authentication. This omissions expose local loopback listeners to DNS rebinding attacks orchestrated by malicious remote websites visited by developers, enabling unauthorized process control and arbitrary command execution.

Alon Barad
Alon Barad
8 views•6 min read