Every CVE Search/ Get API key

CVE-2026-102820

pageant: Out-of-bounds read / oversized allocation in `pageant` MemoryMap::read via a malicious Pageant agent (Windows)

6.2 MediumFix available

pageant provides a [PageantStream] type that implements [AsyncRead] and [AsyncWrite] traits and can be used to talk to a running Pageant instance. Prior to pageant 0.2.3, the Windows pageant crate's pageant/src/wmmessage.rs MemoryMap::read function trusts a peer-controlled u32 response length supplied through the 8192-byte Pageant shared-memory mapping reached by AgentClient::connect_pageant. A local process that impersonates the Pageant window can make query_pageant_direct allocate up to approximately 4 GiB and copy beyond the mapped view, reliably crashing a russh client and conditionally exposing adjacent committed memory. This issue is fixed in pageant 0.2.3.

Attack profile

How easy it is to exploit

Attack vector
Local
Complexity
Low
Privileges needed
None
User interaction
None

What an attacker can affect

Confidentiality
None
Integrity
None
Availability
High

Exploit likelihood

0.19%Up 0.1 points since Sep 30, 2026
90%50%10%1%

What each source reports

CVE List Score used 6.2

pageant: Out-of-bounds read / oversized allocation in `pageant` MemoryMap::read via a malicious Pageant agent (Windows)

pageant provides a [PageantStream] type that implements [AsyncRead] and [AsyncWrite] traits and can be used to talk to a running Pageant instance. Prior to pageant 0.2.3, the Windows pageant crate's pageant/src/wmmessage.rs MemoryMap::read function trusts a peer-controlled u32 response length supplied through the 8192-byte Pageant shared-memory mapping reached by AgentClient::connect_pageant. A local process that impersonates the Pageant window can make query_pageant_direct allocate up to approximately 4 GiB and copy beyond the mapped view, reliably crashing a russh client and conditionally exposing adjacent committed memory. This issue is fixed in pageant 0.2.3.

Record
CVE-2026-102820
CVSS 3.1
6.2 MediumCVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
Weakness
CWE-125, CWE-789
Updated
2026-11-02
EUVDEUVD-2026-89203 6.2

pageant provides a [PageantStream] type that implements [AsyncRead] and [AsyncWrite] traits and can be used to talk to a running Pageant instance. Prior to pageant 0.2.3, the Windows pageant crate's pageant/src/wmmessage.rs MemoryMap::read function trusts a peer-controlled u32 response length supplied through the 8192-byte Pageant shared-memory mapping reached by AgentClient::connect_pageant. A local process that impersonates the Pageant window can make query_pageant_direct allocate up to approximately 4 GiB and copy beyond the mapped view, reliably crashing a russh client and conditionally exposing adjacent committed memory. This issue is fixed in pageant 0.2.3.

Record
EUVD-2026-89203
CVSS 3.1
6.2 MediumCVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
Updated
2026-11-02
GitHub AdvisoriesGHSA-g4mp-vgx3-xrvm 6.2

pageant: Out-of-bounds read / oversized allocation in `pageant` MemoryMap::read via a malicious Pageant agent (Windows)

Summary

MemoryMap::read in the pageant crate (part of the russh workspace, used by russh's SSH-agent client on Windows via AgentClient::connect_pageant) copies a peer-controlled number of bytes out of an 8192-byte shared-memory view with no bounds check — unlike the sibling MemoryMap::write, which correctly rejects oversize access with Error::Overflow. The byte count comes straight from a u32 length prefix that the responding "Pageant" process writes into the shared mapping. A malicious local process that answers as the Pageant agent can therefore cause:

  • an out-of-bounds read past the 8 KiB view (access violation → process crash; or disclosure of adjacent process memory if the following page is committed)
  • an allocation of up to ~4 GiB from a single u32 (vec![0; n]).

This was reproduced end-to-end against the real, unmodified pageant crate (not a model) on x86_64-pc-windows-gnu under Wine; see "Proof of concept".

Impact

  • Availability / DoS (reliable). MemoryMap::read(size) walks off the end of the 8192-byte view and faults on the next, unmapped page — an EXCEPTION_ACCESS_VIOLATION that crashes the russh SSH client. Independently, a size near u32::MAX drives a ~4 GiB vec![0; n] before any copy.
  • Confidentiality (conditional). If memory immediately after the mapped view happens to be committed, read returns those adjacent bytes to russh as the "agent response", which russh then parses as agent identities/signatures. This arm depends on process memory layout, so it is opportunistic; the crash/alloc is the deterministic outcome.
  • Trust boundary. russh locates the agent with FindWindowW("Pageant", "Pageant") and passes the shared-mapping name inside the WM_COPYDATA COPYDATASTRUCT. Any local process can register a window of class + title "Pageant", receive that name, open the same mapping, and write a hostile size. So an unprivileged local process impersonating Pageant can attack every russh-based SSH client that uses the Pageant agent.

Affected component

  • pageant/src/wmmessage.rs
    • MemoryMap::read (:160-171) — no bound (contrast MemoryMap::write :139-158, which returns Error::Overflow when pos + len > length).
    • query_pageant_direct (:199-237) — reads a 4-byte u32 size from the shared mapping (:233) and calls map.read(size) (:234) with no check against _AGENT_MAX_MSGLEN (8192).
  • Reached from russh via AgentClient::connect_pageant → PageantStream → query_pageant_direct.

Platform: Windows only (cfg(windows)), local attacker. Verified against the pageant crate v0.2.2 as shipped in russh v0.63.1 (d3ae702, the latest release). read has never had a bound in any revision (git log -p -- pageant/src/wmmessage.rs).

Details

fn write(&mut self, data: &[u8]) -> Result<(), Error> {
    if self.pos + data.len() > self.length {      // :140  BOUND PRESENT
        return Err(Error::Overflow);
    }
    ... copy_nonoverlapping(&data[0], view+pos, data.len()) ...
}

fn read(&mut self, n: usize) -> Vec<u8> {         // :160  NO BOUND
    let out = vec![0; n];                         // n up to 0xFFFF_FFFF (CWE-789)
    unsafe {
        std::ptr::copy_nonoverlapping(
            self.view.Value.add(self.pos) as *const u8,   // view is length==8192
            out.as_ptr() as *mut u8,
            n,                                    // reads n bytes, may run past the view (CWE-125)
        );
    }
    self.pos += n;
    out
}

query_pageant_direct creates the mapping at _AGENT_MAX_MSGLEN = 8192, writes the request, sends the WM_COPYDATA, then reads the response the peer wrote:

map.seek(0);
let mut buf = map.read(4);
let size = u32::from_be_bytes([buf[0],buf[1],buf[2],buf[3]]) as usize; // :233 peer-controlled
buf.extend(map.read(size));                                            // :234 unbounded

…

Record
GHSA-g4mp-vgx3-xrvm
CVSS 3.1
6.2 MediumCVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
Weakness
CWE-125, CWE-789
Updated
2026-11-02
NVD 6.2

pageant provides a [PageantStream] type that implements [AsyncRead] and [AsyncWrite] traits and can be used to talk to a running Pageant instance. Prior to pageant 0.2.3, the Windows pageant crate's pageant/src/wmmessage.rs MemoryMap::read function trusts a peer-controlled u32 response length supplied through the 8192-byte Pageant shared-memory mapping reached by AgentClient::connect_pageant. A local process that impersonates the Pageant window can make query_pageant_direct allocate up to approximately 4 GiB and copy beyond the mapped view, reliably crashing a russh client and conditionally exposing adjacent committed memory. This issue is fixed in pageant 0.2.3.

Record
CVE-2026-102820
CVSS 3.1
6.2 MediumCVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
Weakness
CWE-125, CWE-789
Updated
2026-11-02
OSV 6.2

pageant: Out-of-bounds read / oversized allocation in `pageant` MemoryMap::read via a malicious Pageant agent (Windows)

pageant provides a [PageantStream] type that implements [AsyncRead] and [AsyncWrite] traits and can be used to talk to a running Pageant instance. Prior to pageant 0.2.3, the Windows pageant crate's pageant/src/wmmessage.rs MemoryMap::read function trusts a peer-controlled u32 response length supplied through the 8192-byte Pageant shared-memory mapping reached by AgentClient::connect_pageant. A local process that impersonates the Pageant window can make query_pageant_direct allocate up to approximately 4 GiB and copy beyond the mapped view, reliably crashing a russh client and conditionally exposing adjacent committed memory. This issue is fixed in pageant 0.2.3.

Record
CVE-2026-102820
CVSS 3.1
6.2 MediumCVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
Weakness
CWE-125, CWE-789
Updated
2026-11-02
OSVDEBIAN-CVE-2026-102820 6.2

pageant provides a [PageantStream] type that implements [AsyncRead] and [AsyncWrite] traits and can be used to talk to a running Pageant instance. Prior to pageant 0.2.3, the Windows pageant crate's pageant/src/wmmessage.rs MemoryMap::read function trusts a peer-controlled u32 response length supplied through the 8192-byte Pageant shared-memory mapping reached by AgentClient::connect_pageant. A local process that impersonates the Pageant window can make query_pageant_direct allocate up to approximately 4 GiB and copy beyond the mapped view, reliably crashing a russh client and conditionally exposing adjacent committed memory. This issue is fixed in pageant 0.2.3.

Record
DEBIAN-CVE-2026-102820
CVSS 3.1
6.2 MediumCVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
Updated
2026-11-02
OSVGHSA-g4mp-vgx3-xrvm 6.2

pageant: Out-of-bounds read / oversized allocation in `pageant` MemoryMap::read via a malicious Pageant agent (Windows)

Summary

MemoryMap::read in the pageant crate (part of the russh workspace, used by russh's SSH-agent client on Windows via AgentClient::connect_pageant) copies a peer-controlled number of bytes out of an 8192-byte shared-memory view with no bounds check — unlike the sibling MemoryMap::write, which correctly rejects oversize access with Error::Overflow. The byte count comes straight from a u32 length prefix that the responding "Pageant" process writes into the shared mapping. A malicious local process that answers as the Pageant agent can therefore cause:

  • an out-of-bounds read past the 8 KiB view (access violation → process crash; or disclosure of adjacent process memory if the following page is committed)
  • an allocation of up to ~4 GiB from a single u32 (vec![0; n]).

This was reproduced end-to-end against the real, unmodified pageant crate (not a model) on x86_64-pc-windows-gnu under Wine; see "Proof of concept".

Impact

  • Availability / DoS (reliable). MemoryMap::read(size) walks off the end of the 8192-byte view and faults on the next, unmapped page — an EXCEPTION_ACCESS_VIOLATION that crashes the russh SSH client. Independently, a size near u32::MAX drives a ~4 GiB vec![0; n] before any copy.
  • Confidentiality (conditional). If memory immediately after the mapped view happens to be committed, read returns those adjacent bytes to russh as the "agent response", which russh then parses as agent identities/signatures. This arm depends on process memory layout, so it is opportunistic; the crash/alloc is the deterministic outcome.
  • Trust boundary. russh locates the agent with FindWindowW("Pageant", "Pageant") and passes the shared-mapping name inside the WM_COPYDATA COPYDATASTRUCT. Any local process can register a window of class + title "Pageant", receive that name, open the same mapping, and write a hostile size. So an unprivileged local process impersonating Pageant can attack every russh-based SSH client that uses the Pageant agent.

Affected component

  • pageant/src/wmmessage.rs
    • MemoryMap::read (:160-171) — no bound (contrast MemoryMap::write :139-158, which returns Error::Overflow when pos + len > length).
    • query_pageant_direct (:199-237) — reads a 4-byte u32 size from the shared mapping (:233) and calls map.read(size) (:234) with no check against _AGENT_MAX_MSGLEN (8192).
  • Reached from russh via AgentClient::connect_pageant → PageantStream → query_pageant_direct.

Platform: Windows only (cfg(windows)), local attacker. Verified against the pageant crate v0.2.2 as shipped in russh v0.63.1 (d3ae702, the latest release). read has never had a bound in any revision (git log -p -- pageant/src/wmmessage.rs).

Details

fn write(&mut self, data: &[u8]) -> Result<(), Error> {
    if self.pos + data.len() > self.length {      // :140  BOUND PRESENT
        return Err(Error::Overflow);
    }
    ... copy_nonoverlapping(&data[0], view+pos, data.len()) ...
}

fn read(&mut self, n: usize) -> Vec<u8> {         // :160  NO BOUND
    let out = vec![0; n];                         // n up to 0xFFFF_FFFF (CWE-789)
    unsafe {
        std::ptr::copy_nonoverlapping(
            self.view.Value.add(self.pos) as *const u8,   // view is length==8192
            out.as_ptr() as *mut u8,
            n,                                    // reads n bytes, may run past the view (CWE-125)
        );
    }
    self.pos += n;
    out
}

query_pageant_direct creates the mapping at _AGENT_MAX_MSGLEN = 8192, writes the request, sends the WM_COPYDATA, then reads the response the peer wrote:

map.seek(0);
let mut buf = map.read(4);
let size = u32::from_be_bytes([buf[0],buf[1],buf[2],buf[3]]) as usize; // :233 peer-controlled
buf.extend(map.read(size));                                            // :234 unbounded

…

Record
GHSA-g4mp-vgx3-xrvm
CVSS 3.1
6.2 MediumCVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
Weakness
CWE-125, CWE-789
Updated
2026-11-02
OSVUBUNTU-CVE-2026-102820 6.2

pageant provides a [PageantStream] type that implements [AsyncRead] and [AsyncWrite] traits and can be used to talk to a running Pageant instance. Prior to pageant 0.2.3, the Windows pageant crate's pageant/src/wmmessage.rs MemoryMap::read function trusts a peer-controlled u32 response length supplied through the 8192-byte Pageant shared-memory mapping reached by AgentClient::connect_pageant. A local process that impersonates the Pageant window can make query_pageant_direct allocate up to approximately 4 GiB and copy beyond the mapped view, reliably crashing a russh client and conditionally exposing adjacent committed memory. This issue is fixed in pageant 0.2.3.

Record
UBUNTU-CVE-2026-102820
CVSS 3.1
6.2 MediumCVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
Updated
2026-11-02

Affected products

Affected packages

Affected packages
PackageAffectedFixed
pageant
crates.io
through 0.2.2
0.2.3
rust-russh
Debian:14
before 0.64.1-1, plus listed versions
0.57.1-10.57.1-2
0.64.1-1
pageant
crates.io
before 0.2.3
0.2.3
rust-russh
Ubuntu:26.10
All versions, plus listed versions
0.57.1-2
None known

History

History
RecordedChangedSources
first indexedCVE List, EUVD, GitHub Advisories, NVD, OSV

Dates are when Every CVE recorded each change. Upstream dates may differ.

In short

CVE-2026-102820 is a medium vulnerability (CVSS 6.2) in Eugeny Russh, published September 29, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.19%, the 8th percentile. Fixed in pageant 0.2.3.

References

Show 4 moreShow less
This page doesn't list everything

Left out here: the rest of 2 source descriptions. The JSON record has them.

MoveEnter Open