high · 8.1CVE-2026-54591Aug 26, 2026

CVE-2026-54591: asyncssh SCP Client Path Traversal to Arbitrary File Write

Rohit Hatagale
AI Security Researcher, SecureLayer7

A malicious SSH server can trick the asyncssh SCP client into writing files anywhere on the victim's filesystem, including shell init files, enabling remote code execution.

Packageasyncssh
Ecosystempip
Affected<= 2.23.0
Fixed in2.23.1
CVE-2026-54591: asyncssh SCP Client Path Traversal to Arbitrary File Write

The problem

The asyncssh SCP client does not sanitize filenames sent by the remote server during a receive operation. The _parse_cd_args function in scp.py returns the server-supplied name verbatim, and _recv_files feeds it directly into posixpath.join(dstpath, name) without stripping path components.

Because posixpath.join resolves ../ segments, a server-controlled name like ../../../home/user/.bashrc silently lands outside the intended download directory. By chaining D (enter-directory) and C (create-file) SCP protocol messages, an attacker can escape any target directory and overwrite arbitrary files.

This is the same vulnerability class as CVE-2019-6111 in OpenSSH, which OpenSSH mitigated years ago.

Proof of concept

A working proof-of-concept for CVE-2026-54591 in asyncssh, with the exact payload below.

text
# Malicious SCP server sends this wire-protocol sequence.
# Client called: await asyncssh.scp((conn, 'file'), '/home/user/downloads/')
#
# Step 1: enter a fake subdirectory whose name traverses up
D0755 0 ..
# Step 2: enter again to reach home dir
D0755 0 ..
# Step 3: drop a payload into .ssh/authorized_keys
C0644 84 authorized_keys
<attacker-pubkey-blob>
E
E

# Alternatively, single-step traversal for a simple file overwrite:
C0644 47 ../../../home/user/.bashrc
<shell-payload>

The root cause is the absence of a posixpath.basename() call (or equivalent .. check) on the name value returned by _parse_cd_args before it is joined to dstpath. The fix in commit d730803b strips any path separators and .. components from the server-supplied filename, so only the final component is ever joined to the destination path.

The D (directory) message makes the vulnerability more powerful: each D action pushes a new working path, and a name of .. causes posixpath.join to ascend one level per step. Chaining enough D messages lets the attacker walk all the way to any world-writable directory on the system before issuing a C (file-create) message.

CWE-22 (Path Traversal). CVSS 8.1 (High): network-reachable, low complexity, no privileges required on the victim side, high integrity impact.

The fix

Upgrade asyncssh to 2.23.1 or later. The patch (commit d730803b) applies posixpath.basename() to the name parsed from every C and D SCP protocol message before constructing the local destination path, ensuring filenames with ../ components can never escape the target directory.

Reporter not attributed.

References: [1][2][3][4][5]

Related research