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-39827

CVE-2026-39827: Denial of Service via Unbounded Memory Growth in Go SSH (golang.org/x/crypto/ssh)

Amit Schendel
Amit Schendel
Senior Security Researcher

Jun 26, 2026·6 min read·3 visits

Executive Summary (TL;DR)

A memory leak in golang.org/x/crypto/ssh prior to version 0.52.0 allows authenticated clients to trigger a Denial of Service by repeatedly sending channel requests that the server rejects.

An unbounded memory leak vulnerability in the Go SSH package (golang.org/x/crypto/ssh) allows authenticated users to crash the server by repeatedly requesting connection channels that are rejected, leading to system resource exhaustion.

Vulnerability Overview

The vulnerability CVE-2026-39827 represents a critical memory leak flaw in the golang.org/x/crypto/ssh package, which is Go's official implementation of the SSH protocol.

This package is widely used to develop custom SSH daemons, remote administration agents, container orchestration handlers, and secure Git hosting applications. When a server exposes an SSH endpoint using this library, it establishes a multiplexed transport channel structure to manage multiple virtual channels over a single physical TCP connection.

The vulnerability is classified under CWE-401 (Missing Release of Memory after Effective Lifetime). It is triggered when an authenticated client requests a logical channel that the server application rejects, leading to an unbounded memory leak that eventually causes a Denial of Service due to system resource exhaustion.

Root Cause Analysis

To understand the root cause of CVE-2026-39827, it is necessary to examine how the Go SSH multiplexer manages connection states. Under normal operation, when a client sends an SSH_MSG_CHANNEL_OPEN packet, the server's multiplexer (mux) assigns a localId to trace the request and registers it in its internal map (mux.chanList). This list acts as a registry to route incoming traffic correctly.

Once registered, the multiplexer delivers a NewChannel object to the server's high-level application handler. The application determines whether to allow the channel based on authorization, resource usage, or requested services. If the application decides to deny the request, it invokes the Reject() function.

The flaw lies in the original implementation of the Reject() function in ssh/channel.go. While the method updated the channel's internal state machine and sent the appropriate rejection packet to the client, it completely omitted any code to clean up the registration record inside the connection's chanList map.

Because the multiplexer maintains a strong reference to the rejected channel throughout the lifetime of the underlying TCP session, the Go garbage collector is unable to reclaim any of the allocated memory. This includes the internal channel structures, input/output packet queues, and synchronization channels, resulting in a persistent memory leak.

Code-Level Patch Analysis

The following Mermaid diagram outlines the vulnerable channel setup state vs. the corrected cleanup flow.

In the vulnerable implementation, the Reject() function processed the rejection and returned immediately, leaving the channel registered. Let us analyze the difference introduced in the patch.

// Vulnerable Code Path
func (ch *channel) Reject(reason RejectionReason, message string) error {
	reject := chanOpenConfirmMsg{
		// ... fields mapped ...
	}
	ch.decided = true
	return ch.sendMessage(reject) // Exit without cleaning up chanList
}
// Patched Code Path (6c195c8a97ae3d91a366ebdd7787d5faa64bf42a)
func (ch *channel) Reject(reason RejectionReason, message string) error {
	reject := chanOpenConfirmMsg{
		// ... fields mapped ...
	}
	ch.decided = true
	err := ch.sendMessage(reject)
 
	// Remove the channel from the mux to prevent memory leaks.
	// Do not call ch.close() here: no goroutine holds a reference to a
	// rejected channel's internal channels (msg, incomingRequests), so
	// removing it from chanList is sufficient for GC. Calling close()
	// would race with the mux loop goroutine (handlePacket or dropAll),
	// causing a panic from closing an already-closed channel.
	ch.mux.chanList.remove(ch.localId)
 
	return err
}

As annotated in the fix, the developers deliberately avoided calling ch.close(). Doing so would trigger a severe race condition against the multiplexer's packet handling loops, which would crash the runtime with a panic. Simply deleting the reference from the map allows the garbage collector to safely sweep up the unused allocations.

Exploitation Methodology

An attacker must establish an authenticated SSH connection to exploit this vulnerability. No authorization privileges beyond standard authentication are required, meaning any standard user or automated service account with SSH access can perform the attack.

The attack begins when the client issues a loop of consecutive SSH_MSG_CHANNEL_OPEN requests. To trigger the memory leak, the client requests a channel type that the server is configured to reject. Common examples include requesting TCP port forwarding or custom subsystem channels when such features are disabled.

Every rejected attempt allocates a fresh channel context containing memory structures that remain resident in RAM. By scripting a rapid cycle of channel open requests over a single persistent connection, an attacker can leak megabytes of memory per minute. This process eventually causes memory pressure to escalate to the point where the operating system's Out-Of-Memory killer terminates the SSH server process, resulting in a complete Denial of Service.

Impact Assessment

The vulnerability carries a CVSS base score of 6.5, reflecting a medium-severity threat. The primary security impact is complete loss of Availability for the host application, while Confidentiality and Integrity remain uncompromised.

In real-world environments, this vulnerability is highly critical for multi-user systems. For instance, code hosting platforms like Gitea or enterprise Git-over-SSH servers are exposed to authenticated Denial of Service attacks. A single malicious user account can crash the container or the entire infrastructure hosting the service.

Furthermore, because many container environments use static binaries compiled with Go, updating the system library requires compiling the parent projects from scratch. This introduces significant lag in patching deployment pipelines.

Detection and Remediation

The definitive remediation for CVE-2026-39827 is updating the Go crypto dependency to version 0.52.0 or higher. Developers can upgrade the package by executing the command go get golang.org/x/crypto@v0.52.0 and rebuilding all dependent applications.

For environments where immediate rebuilding is not feasible, security administrators can monitor for signs of active exploitation. Intrusion detection systems should check for an abnormal frequency of SSH_MSG_CHANNEL_OPEN_FAILURE (type 92) messages originating from a single session.

Additionally, host-level metrics should monitor SSH daemon process memory. A linear, continuous rise in RSS memory without a corresponding drop indicates an active leak scenario and should trigger automated session termination or rate limiting.

Official Patches

GoGerrit Commit Details
GoGerrit Change List CL 781320

Fix Analysis (1)

Technical Appendix

CVSS Score
6.5/ 10
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H
EPSS Probability
0.20%
Top 90% most exploited

Affected Systems

Go application servers using golang.org/x/crypto/ssh to run SSH server-side servicesGitea SSH serversDocker/Podman daemon SSH componentsHashiCorp Vault SSH secrets engine

Affected Versions Detail

Product
Affected Versions
Fixed Version
golang.org/x/crypto/ssh
Go
< 0.52.00.52.0
AttributeDetail
CWE IDCWE-401
Attack VectorNetwork (AV:N)
CVSS Score6.5 (Medium)
EPSS Score0.00196
ImpactDenial of Service (DoS) / Memory Exhaustion
Exploit StatusNone (No public exploits)
KEV StatusNot listed

MITRE ATT&CK Mapping

T1499.003Endpoint Denial of Service: System Resource Overload
Impact
T1499.004Endpoint Denial of Service: Application Exhaustion Flood
Impact
CWE-401
Missing Release of Memory after Effective Lifetime

The system does not release memory after its effective lifetime has ended, which can lead to resource exhaustion.

Vulnerability Timeline

Go Issue #35127 is opened identifying channel leak after Reject()
2019-10-24
Developer Nicola Murino creates the patch
2026-03-01
Gerrit CL 781320 is reviewed, tested via LUCI TryBots, and merged
2026-05-21
CVE-2026-39827 is published in NVD and CVE databases
2026-05-22
CVE metadata updated with further details
2026-06-17

References & Sources

  • [1]Gerrit Change List 781320
  • [2]Go Review Source Code
  • [3]Go GitHub Issue #35127
  • [4]Go Vulnerability Database Advisory
  • [5]CVE-2026-39827 Record

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

•10 minutes ago•CVE-2026-39828
6.3

CVE-2026-39828: Go SSH Server PartialSuccessError Permissions Discard Bypass

A critical security bypass vulnerability was discovered in the Go SSH server implementation within the golang.org/x/crypto/ssh package. When an SSH server authentication callback returned a PartialSuccessError alongside non-nil Permissions, the server silently discarded these permissions before the subsequent authentication step. Consequently, once the user completed the second-factor authentication, the session-level restrictions were dropped, granting the client unauthorized capabilities.

Amit Schendel
Amit Schendel
1 views•7 min read
•about 1 hour ago•CVE-2026-39835
5.3

CVE-2026-39835: Remote Denial of Service via Null Pointer Dereference in Go SSH CertChecker

A Denial of Service (DoS) vulnerability exists in the Go SSH implementation package (golang.org/x/crypto/ssh). The vulnerability is caused by a null pointer dereference (runtime panic) when CertChecker is utilized as a public key callback but its validation fields, IsUserAuthority or IsHostAuthority, are uninitialized.

Amit Schendel
Amit Schendel
4 views•7 min read
•about 2 hours ago•CVE-2026-39830
9.1

CVE-2026-39830: Unsolicited Response Channel Deadlock and Resource Leak in golang.org/x/crypto/ssh

A denial-of-service (DoS) and resource leak vulnerability in the Go SSH package (golang.org/x/crypto/ssh) allows a malicious peer to permanently deadlock connection processing loops and leak memory. This issue stems from improper handling of unsolicited responses at the global and channel layers, which saturate internal bounded channel buffers and block the main multiplexer loop. The vulnerability is fully resolved in version 0.52.0.

Alon Barad
Alon Barad
3 views•7 min read
•about 4 hours ago•CVE-2026-39829
7.5

CVE-2026-39829: Denial of Service in Go SSH Parser

A high-severity Denial of Service (DoS) vulnerability exists in the golang.org/x/crypto/ssh package prior to version 0.52.0. The vulnerability is caused by a lack of size and range validation on incoming RSA and DSA public key parameters during SSH authentication. An unauthenticated attacker can submit a crafted public key with pathologically large parameters, triggering intensive CPU computation during signature verification and leading to a complete Denial of Service.

Alon Barad
Alon Barad
4 views•5 min read
•about 7 hours ago•CVE-2026-39831
9.1

CVE-2026-39831: Authentication Bypass in golang.org/x/crypto/ssh via FIDO/U2F User Presence Bypass

An authentication bypass vulnerability was identified in the golang.org/x/crypto/ssh package. The library's verification logic for FIDO/U2F security keys failed to check the User Presence (UP) flag. This omission allows an attacker with access to a hardware token interface or an agent-forwarding socket to authenticate without physical user interaction.

Alon Barad
Alon Barad
5 views•5 min read
•about 7 hours ago•CVE-2026-39834
9.1

CVE-2026-39834: Infinite Loop and CPU Exhaustion via Integer Truncation in Go SSH Channel Write

A critical vulnerability exists in the Go SSH sub-repository (golang.org/x/crypto/ssh) before version 0.52.0. When an application writes payloads of 4GB or larger in a single write operation, integer truncation in the remote window calculation causes an infinite loop. This results in complete CPU core exhaustion and a denial-of-service condition.

Amit Schendel
Amit Schendel
7 views•7 min read