Oct 1, 2026·5 min read·5 visits
Unvalidated 32-bit response length fields in the pageant crate allow a local process to cause an out-of-memory crash or perform out-of-bounds reads against russh-based clients.
A critical memory handling vulnerability exists in the pageant crate, a workspace component of the Rust-based russh SSH client library, during communication with the PuTTY Pageant SSH agent on Windows systems. Prior to version 0.2.3, the library's shared memory parsing logic blindly trusted a peer-controlled, 32-bit big-endian response length field. This allows local attackers running within the same user session to trigger out-of-bounds reads or execute an out-of-memory crash of the client application.
The pageant crate functions as a workspace utility inside the russh SSH client library, facilitating communications with the PuTTY Pageant SSH agent on Windows systems.
This communication depends on local Inter-Process Communication (IPC) involving Windows Messaging (WM_COPYDATA) and Shared Memory Map Views. The client establishes a shared file mapping with a static capacity constraint of 8,192 bytes (8 KiB) and passes this file name to the Pageant agent, which then writes responses directly to the shared space.
The vulnerability is located in the MemoryMap::read parser within the pageant/src/wmmessage.rs file. By failing to validate the boundaries of incoming messages, the parser exposes the client program's runtime memory to crashes or local information leaks. This flaw represents a severe design oversight when handling boundaries inside shared memory mappings.
The root cause of the vulnerability lies in the implementation of the MemoryMap::read stream reader and its interaction with the query_pageant_direct handler. When reading raw responses, the client first reads a 4-byte length prefix directly from the shared memory view, parsing it as a big-endian u32 value assigned to the variable size.
Because the peer process (which can be impersonated by any standard user process on the same desktop environment) fully controls this shared memory view, the size variable can be manipulated to contain arbitrary values. The library then executes MemoryMap::read(size) without validating whether the requested index range (self.pos + size) exceeds the physical size of the memory map (self.length), which is typically bounded at 8,192 bytes.
This lack of validation triggers two primary failure modes: first, an Out-of-Memory (OOM) abort via CWE-789 due to an excessive vector allocation size request; and second, an Out-of-Bounds Read (CWE-125) during the execution of std::ptr::copy_nonoverlapping inside an unsafe block. If the copy operation points to adjacent unmapped system space, the OS terminates the process with an access violation.
The sequence of IPC messaging and the interception point where a malicious local process triggers the crash are represented in the flowchart below.
This architecture highlights that the security of this local communication depends entirely on verifying boundary limits during the parsing phase, since the Windows Messaging API does not inherently isolate client-to-agent channel registrations within standard interactive sessions.
An inspection of the vulnerable source code confirms that raw pointer operations were executed without bounds checking.
Below is the vulnerable implementation of the reader function:
// VULNERABLE: Prior to pageant version 0.2.3
impl MemoryMap {
fn read(&mut self, n: usize) -> Vec<u8> {
let out = vec![0; n]; // CWE-789: Excessive memory allocation if 'n' is massive
unsafe {
std::ptr::copy_nonoverlapping(
self.ptr.add(self.pos),
out.as_ptr() as *mut u8,
n, // CWE-125: Out-of-bounds pointer copy if 'self.pos + n' > self.length
);
}
self.pos += n;
out
}
}To address this vulnerability, the maintainers refactored the function's signature and introduced boundary validation checks:
// PATCHED: pageant version 0.2.3
impl MemoryMap {
fn read(&mut self, n: usize) -> Result<Vec<u8>, Error> {
// Validate bounds and prevent integer overflow using checked_add
if self.pos.checked_add(n).is_none_or(|end| end > self.length) {
return Err(Error::Overflow);
}
let out = vec![0; n];
unsafe {
std::ptr::copy_nonoverlapping(
self.ptr.add(self.pos),
out.as_ptr() as *mut u8,
n,
);
}
self.pos += n;
Ok(out)
}
}This patch adds robust boundary checking. Using checked_add prevents integer wrapping attacks when calculating memory offsets, and checking end > self.length prevents reads from exceeding the size of the 8,192-byte file mapping. These modifications ensure that memory is only allocated if the request falls within the active map boundaries.
Exploiting this flaw requires local code execution within the victim's Windows session. This scenario is common in shared development server environments or terminal environments containing multi-user services.
An attacker can register a window class matching the standard name of the legitimate PuTTY Pageant program (Pageant). If the genuine Pageant agent is not running, the victim client's call to connect_pageant will target the malicious window handle. When the client transmits a request and waits for an answer, the attacker-controlled window receives the notification, writes a payload containing 0xFFFFFFFF into the first four bytes of the shared mapping, and signals the client to resume.
Upon parsing this length, the client allocates a 4 GiB buffer. Because standard 32-bit and some 64-bit user processes lack the memory allocation headroom for an immediate block allocation of this scale, the memory manager aborts the program. If the attacker specifies a size exceeding the remaining unread buffer but within system allocation limits, the copy_nonoverlapping function reads adjacent heap memory, exposing potential secrets if the application subsequently processes, logs, or transmits this data.
The CVSS vector is rated as CVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H, yielding a severity score of 6.2.
The attack vector is local (AV:L) because triggering the condition requires interacting with local Windows API messaging loops. Attack complexity is low (AC:L) because standard programmatic window registration and shared memory access do not require advanced administrative rights on Windows systems.
While the official classification rates Confidentiality Impact as None (C:N), the presence of an out-of-bounds pointer copy operation means that adjacent heap contents could be copied into the output vector. Depending on how the client application processes error buffers, this could lead to the exposure of other private SSH keys or session structures.
CVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H| Product | Affected Versions | Fixed Version |
|---|---|---|
pageant Eugeny | < 0.2.3 | 0.2.3 |
russh Eugeny | >= 0.58.0, < 0.63.2 | 0.63.2 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-125, CWE-789 |
| Attack Vector | Local |
| CVSS v3.1 Score | 6.2 (Medium) |
| EPSS Score | 0.00129 (0.129% probability) |
| Impact | Denial of Service (DoS) and potential Information Disclosure |
| Exploit Status | poc |
| KEV Status | Not Listed |
The software reads data past the end, or before the beginning, of the intended buffer, or allocates memory with an excessive size value.
An authorization bypass and path traversal vulnerability exists in the SiYuan knowledge workspace platform. The vulnerability is located in the '/api/file/getUniqueFilename' endpoint inside the 'github.com/siyuan-note/siyuan/kernel' package. Under default configurations, this route is exposed to users who satisfy basic authentication middleware checks, which includes anonymous readers in publish mode. By supplying unvalidated absolute paths, remote attackers can verify the existence of files and directories across the host operating system, establishing a high-fidelity file existence oracle.
A highly critical Regular Expression Denial of Service (ReDoS) vulnerability in basic-ftp, an FTP client library for Node.js. In versions prior to 6.2.1, a malicious or compromised FTP server can exploit this vulnerability to force the FTP client to consume quadratic CPU time during directory parsing. This issue blocks the single-threaded Node.js event loop, freezing the application process and leading to a complete Denial of Service (DoS).
An uncontrolled resource consumption vulnerability in the russh library allows remote authenticated attackers to exhaust server memory (heap) by flooding channel open requests during a stalled key re-exchange (rekeying) process, causing a denial of service via Out-of-Memory (OOM) termination.
A validation bypass vulnerability exists in Fastify web framework prior to version 5.12.2. The flaw stems from shallow normalization of header validation schemas, which fails to lowercase nested or conditional schema rules (like JSON Schema dependencies or dependentRequired) defined in mixed or canonical casing. Consequently, because Node.js normalizes incoming HTTP request headers to lowercase, the compiled validator fails to match these headers against the un-normalized mixed-case schema triggers, silently skipping conditional checks and allowing unauthenticated attackers to bypass authorization or security headers.
CVE-2026-84469 is a high-severity request validation bypass vulnerability in the Fastify Node.js web framework. In versions prior to 5.12.2, Fastify uses loose truthiness checks to decide whether to compile request schemas. When a component (such as the body) is explicitly configured with a boolean 'false' schema—which under JSON Schema Draft 7 acts as a 'deny-all' constraint—Fastify's internal logic evaluates this as a falsy value and skips compilation entirely. This allows unauthenticated remote attackers to send arbitrary payloads to these endpoints, bypassing validation checks and directly executing backend route handlers.
An authentication bypass vulnerability in the Fastify web framework allows remote attackers to access private custom not-found handlers by submitting requests with malformed URLs. This bypasses the typical request lifecycle and its associated authorization hooks.