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·61 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

•about 20 hours ago•CVE-2026-62374
7.1

CVE-2026-62374: Silent Claim-Set Reduction and Verification Bypass in SD JWT JS

CVE-2026-62374 (GHSA-f9j6-8p6x-r9j6) is a verification bypass vulnerability in the OpenWallet Foundation SD JWT JS library (@sd-jwt/core and @sd-jwt/decode versions 0.19.0 and earlier). Due to permissive UTF-8 decoding and the omission of mandatory reference checks during presentation verification, tampered or unreferenced disclosures are silently dropped rather than rejected. This deviates from RFC 9901 §7.1 requirements and allows attackers to execute silent claim-set reduction attacks against relying parties.

Alon Barad
Alon Barad
9 views•10 min read
•about 21 hours ago•GHSA-J656-3HF2-FVJC
6.1

GHSA-j656-3hf2-fvjc: Read-Only SQL Validation Bypass via Comment Interpretation Conflict in Bytebase DBHub

An interpretation conflict in Bytebase DBHub (< 0.22.6) allows attackers to bypass read-only SQL query restrictions when connected to MySQL or MariaDB instances. Because DBHub's custom SQL tokenizer treats any '--' sequence as a comment, whereas MySQL and MariaDB require trailing whitespace or a control character, crafted queries containing '--' immediately followed by non-whitespace characters allow stacked destructive SQL statements to execute on connections configured as read-only.

Alon Barad
Alon Barad
6 views•9 min read
•3 days ago•CVE-2026-118777
4.8

CVE-2026-118777: Prototype Pollution in Forge HTTP Client Cookie Management

CVE-2026-118777 is a prototype pollution vulnerability (CWE-1321) in the Forge JavaScript cryptography and networking library (distributed on npm as node-forge) prior to version 1.4.1. The flaw resides in the forge.http client subsystem, where incoming HTTP cookie names and paths parsed from Set-Cookie response headers are stored directly into standard JavaScript objects without key validation or property isolation. By returning crafted Set-Cookie headers containing keys such as __proto__ or constructor, a malicious HTTP server can inject arbitrary properties into Object.prototype, attach attributes to the global Object constructor, or delete built-in prototype methods to cause an application-wide denial of service.

Amit Schendel
Amit Schendel
10 views•10 min read
•3 days ago•CVE-2026-118775
3.7

CVE-2026-118775: ASN.1 OID First Arc Truncation and Ambiguity in node-forge

CVE-2026-118775 (GHSA-4642-5mcj-2rqw) is an integer overflow and validation flaw in the ASN.1 serialization module of Forge (node-forge) prior to version 1.4.1. The asn1.oidToDer() function fails to validate the range of the first two arcs of an Object Identifier (OID) and truncates the packed initial subidentifier to a single 8-bit integer. Applications that perform policy checks on untrusted OID strings before encoding them into Distinguished Encoding Rules (DER) format can be tricked into emitting DER bytes that correspond to a completely different, restricted OID.

Amit Schendel
Amit Schendel
11 views•10 min read
•3 days ago•CVE-2026-119194
7.5

CVE-2026-119194: Algorithmic Complexity Denial of Service in pyasn1 Schemaless ASN.1 Decoder

CVE-2026-119194 is an algorithmic complexity vulnerability (CWE-407) in the pyasn1 library for Python, affecting versions 0.3.3 through 0.6.4. The flaw resides in the schemaless decoding routine ConstructedPayloadDecoderBase._decodeComponentsSchemaless used across BER, CER, and DER codecs. By sending an ASN.1 container populated with child components whose tag identifiers are separated by multiples of CPython's integer hash modulus (sys.hash_info.modulus), an unauthenticated attacker can force worst-case hash collisions in an unbounded Python set, degrading decoding performance from O(N) to O(N^2) and causing a Denial of Service (DoS).

Alon Barad
Alon Barad
9 views•9 min read
•3 days ago•CVE-2026-119195
7.5

CVE-2026-119195: Quadratic-Time Denial of Service in pyasn1 BER/CER/DER Decoders

CVE-2026-119195 is an algorithmic complexity vulnerability (CWE-407) in the pyasn1 library for Python, affecting all versions prior to 0.6.5. When decoding constructed strings or indefinite-length ANY types across BER, CER, and certain DER code paths, the payload decoders repeatedly concatenate incoming fragments onto an immutable bytes object using the += operator. Because Python bytes objects cannot be resized in-place, each fragment iteration allocates a new buffer and copies all previously accumulated bytes, resulting in quadratic O(N^2) time and memory copy complexity. An unauthenticated remote attacker can supply a highly fragmented ASN.1 stream to exhaust CPU cycles and stall application worker threads.

Amit Schendel
Amit Schendel
10 views•10 min read