Skip to main content
CVE Vulnerability Database
Vulnerability Database/CVE-2025-65947

CVE-2025-65947: thread-amount DOS Vulnerability

CVE-2025-65947 is a denial of service vulnerability in thread-amount caused by resource leaks on Windows and Apple platforms. This post covers the technical details, affected versions, impact, and mitigation.

Updated:

CVE-2025-65947 Overview

CVE-2025-65947 affects thread-amount, a Rust library that returns the number of threads in the current process. Versions prior to 0.2.2 contain resource leaks in the Windows and Apple platform implementations. The Windows path leaks kernel handles by failing to call CloseHandle on the snapshot returned by CreateToolhelp32Snapshot. The Apple path leaks memory by failing to call vm_deallocate on the thread list returned by task_threads. Repeated calls exhaust process handles or memory, leading to denial of service.

Critical Impact

Repeated invocation of thread_amount() exhausts process handles on Windows or triggers the OOM killer on macOS and iOS, terminating the host application.

Affected Products

  • thread-amount crate versions prior to 0.2.2 on Windows
  • thread-amount crate versions prior to 0.2.2 on macOS
  • thread-amount crate versions prior to 0.2.2 on iOS

Discovery Timeline

  • 2025-11-21 - CVE-2025-65947 published to NVD
  • 2026-04-15 - Last updated in NVD database

Technical Details for CVE-2025-65947

Vulnerability Analysis

The vulnerability is a resource leak [CWE-400] in two platform-specific implementations of the thread_amount() function. On Windows, the function obtains a snapshot handle from CreateToolhelp32Snapshot and iterates threads using Thread32First and Thread32Next, but never releases the handle. Each call permanently consumes one entry from the per-process handle table, which is bounded by the Windows kernel.

On Apple platforms, the function uses the Mach kernel API task_threads to retrieve a thread_act_array_t allocated in the caller's virtual memory. The original implementation discards the pointer without calling mach_vm_deallocate. Every call leaks the memory backing the thread list, growing the resident set until the operating system terminates the process.

Root Cause

The root cause is missing cleanup of operating system resources returned by kernel APIs. The Windows code path omits CloseHandle on the toolhelp snapshot. The Apple code path omits mach_vm_deallocate on the thread array. Neither implementation used Rust's RAII patterns to guarantee release, so resources accumulate across repeated calls in long-running processes.

Attack Vector

An attacker capable of triggering repeated calls to thread_amount(), for example through a network-exposed endpoint in a service that uses the crate for metrics or health checks, can drive the host process to handle or memory exhaustion. No authentication or user interaction is required when the calling application exposes the code path remotely.

rust
// Source: https://github.com/jzeuzs/thread-amount/commit/28860d4a38286609cb884c13b5b7941edc2390e5
// Patch in src/osx.rs - adds mach_vm_deallocate to release the thread list
 use std::num::NonZeroUsize;
+use std::{mem, ptr};
 
 use mach2::kern_return::KERN_SUCCESS;
+use mach2::mach_types::thread_act_array_t;
+use mach2::message::mach_msg_type_number_t;
+use mach2::port::mach_port_t;
 use mach2::task::task_threads;
 use mach2::traps::mach_task_self;
+use mach2::vm::mach_vm_deallocate;
+use mach2::vm_types::{mach_vm_address_t, mach_vm_size_t};
 
 pub(crate) fn thread_amount() -> Option<NonZeroUsize> {
-    let mut state = [0u32; 1296];
-    let mut count: u32 = 0;
-    let rc = unsafe {
-        task_threads(
-            mach_task_self(),
-            &mut state.as_mut_ptr() as *mut *mut u32,
-            &mut count as *mut _,
-        )
-    };
+    unsafe {
+        let task = mach_task_self();
+        let mut thread_list: thread_act_array_t = ptr::null_mut();
+        let mut count: mach_msg_type_number_t = 0;
+        let rc = task_threads(task, &mut thread_list, &mut count);

The Windows patch imports CloseHandle from windows::Win32::Foundation and invokes it on the snapshot handle returned by CreateToolhelp32Snapshot before the function returns. See the GitHub Pull Request #29 for the complete diff.

Detection Methods for CVE-2025-65947

Indicators of Compromise

  • Steady, monotonic growth of the per-process handle count on Windows hosts running services that depend on thread-amount versions earlier than 0.2.2.
  • Sustained increase in resident set size (RSS) and virtual memory on macOS or iOS processes that call thread_amount() repeatedly.
  • Unexpected process termination correlated with STATUS_NO_MEMORY, OOM killer log entries, or Windows handle-limit errors.

Detection Strategies

  • Audit Rust dependency manifests (Cargo.lock) for thread-amount entries with versions below 0.2.2.
  • Use runtime telemetry to track handle count and memory growth of services that invoke thread-counting routines on a schedule.
  • Inspect crash logs and core dumps for repeated terminations of the same process when handle or memory ceilings are reached.

Monitoring Recommendations

  • Alert on Windows processes whose handle count grows linearly over time without an offsetting decrease.
  • Monitor macOS and iOS workloads for RSS growth rates that exceed expected baselines, especially in long-running daemons.
  • Forward process termination and OOM events to a centralized log pipeline to correlate with deployments of vulnerable crate versions.

How to Mitigate CVE-2025-65947

Immediate Actions Required

  • Upgrade the thread-amount dependency to version 0.2.2 or later in all Rust projects.
  • Rebuild and redeploy any application that statically links the vulnerable crate; cargo lockfile updates alone are insufficient.
  • Restart long-running processes that have already accumulated leaked handles or memory.

Patch Information

The maintainers released version 0.2.2 containing the fix in commit 28860d4. The patch adds CloseHandle on Windows and mach_vm_deallocate on Apple platforms. Full details are in the GitHub Security Advisory GHSA-jf9p-2fv9-2jp2.

Workarounds

  • Replace calls to thread_amount() with platform-native code that explicitly releases the toolhelp snapshot and Mach thread array.
  • Cache the result of thread_amount() for the lifetime of the process or for a long interval to limit invocation frequency.
  • Restart affected services on a schedule until the upgrade to 0.2.2 is deployed.
bash
# Update the dependency in Cargo.toml and refresh the lockfile
cargo update -p thread-amount --precise 0.2.2
cargo build --release

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.