GHSA-2wxc-x7rj-hg8f: Path Traversal
| | | |---|---| | Product | asyncssh (all versions through 2.23.0) | | Related | CVE-2019-6111 (same class in OpenSSH) | | Fix | AsyncSSH 2.23.1 |
A malicious SSH server can write arbitrary files on the asyncssh SCP client's filesystem by sending filenames containing ../ traversal sequences. The SCP receive path does not currently sanitize server-provided filenames. By chaining directory traversals via the D (directory) action, an attacker can escape any target directory and overwrite ~/.bashrc, ~/.ssh/rc, or ~/.ssh/authorizedkeys, achieving code execution. This is the same vulnerability class as CVE-2019-6111. The mitigation applied in OpenSSH does not appear to have been adopted in asyncssh.
---
Steps to exploit:
Step 1 - Normal usage: Application calls await asyncssh.scp((conn, 'file'), '/home/user/downloads/'). This is the standard, documented API.
Step 2 - SCP protocol: asyncssh opens an SSH exec channel, runs scp -f file. The server controls the filename field:
C0644 100 ../pwned.txt\n (simple traversal)
D0755 0 ..\n (traverse up, repeat as needed) C0644 47 .bashrc\n (write payload) E\n
Step 3 - parsecdargs (scp.py:134-142) returns the filename verbatim:
python def parsecdargs(args: bytes) -> Tuple[int, int, bytes]: permissions, size, name = args.split(None, 2) return int(permissions, 8), int(size), name # no sanitization
The returned name is not passed through basename() and is not checked for .. or / components.
Step 4 - recvfiles (scp.py:706-713) joins the unsanitized name:
python newdstpath = posixpath.join(dstpath, name)
With dstpath=b'/home/user/downloads/subdir' and name=b'../pwned.txt', this resolves to /home/user/downloads/pwned.txt, outside the target.
Step 5 - File write: recvfile opens the traversed path via self.fs.open(dstpath, 'wb') and writes attacker-controlled content. The resolved path is not checked against the target directory boundary.
Step 6 - RCE chains:
| Target | Execution trigger | Reliability | |---|---|---| | ~/.bashrc | Next terminal open | High | | ~/.profile | Next login | High | | ~/.ssh/rc | Next SSH connection (requires sshd) | High | | ~/.ssh/authorizedkeys | Attacker logs in with command= | Medium |
---
Reproduction:
Link to reproduction script: pathtraversalpoc.zip
bash docker build -t asyncssh-scp-traversal -f Dockerfile . docker run --rm asyncssh-scp-traversal
The attached pocscptraversal.py starts a malicious SSH server in-process using asyncssh's own API, then downloads from it via asyncssh.scp().
Expected Output:
<img width="1400" height="815" alt="image" src="https://github.com/user-attachments/assets/496745e4-d11d-4ed8-bddd-d15dd13d1751" />
Affected Software
Remediation
Recommended actions to resolve this vulnerability, in priority order.
- Upgrade
Upgrade
pip/asyncsshto a version that resolves this vulnerability.Fixed in 2.23.1 - Upgrade
Upgrade
asyncsshto a version that resolves this vulnerability.Fixed in 2.23.1 - Configuration
Mitigate the SCP path traversal by sanitizing server-provided filenames and ensuring the resolved destination path is checked against the intended target directory boundary (reject/normalize any `..` or path separator components before calling `self._fs.open(dstpath, 'wb')`).
asyncssh.scp (SCP receive path handling) server-provided SCP filename sanitization / destination path boundary check = enabled
Event History
Frequently Asked Questions
Who is exposed to this issue?
Applications using AsyncSSH SCP client receive operations are exposed when they connect to a malicious or compromised SSH server. The affected behavior is present in AsyncSSH versions through 2.23.0.
What does an attacker need to exploit it?
The attacker needs to control the SSH/SCP server contacted by the client and induce the client to receive files using SCP. No client-side privileges are required, but user interaction is required because the client must initiate the SCP transfer.
Are normal SCP download calls affected?
Yes. The documented pattern of calling asyncssh.scp() to copy a remote file into a local download directory is affected because the server controls SCP filename and directory records.
What is the impact if exploitation succeeds?
A malicious server can escape the intended local destination using ../ sequences and write arbitrary files on the client filesystem. It can overwrite files such as ~/.bashrc, ~/.ssh/rc, or ~/.ssh/authorized_keys, which may lead to code execution.
What should be done if upgrading cannot happen immediately?
Do not use the AsyncSSH SCP client to download from untrusted or potentially compromised SSH servers. The available fix is AsyncSSH 2.23.1.