{"id":"CVE-2026-54591","aliases":["DEBIAN-CVE-2026-54591","EUVD-2026-42399","GHSA-2wxc-x7rj-hg8f","PYSEC-2026-3808","UBUNTU-CVE-2026-54591"],"status":"published","title":"AsyncSSH: SCP Path Traversal to Arbitrary File Write","description":"AsyncSSH is a Python package which provides an asynchronous client and server implementation of the SSHv2 protocol on top of the Python asyncio framework. Prior to 2.23.1, a malicious SSH server can write arbitrary files on the asyncssh SCP client's filesystem by sending filenames containing ../ traversal sequences because _parse_cd_args in scp.py returns server-provided names verbatim and _recv_files joins them to the destination path without enforcing the target directory boundary. This issue is fixed in version 2.23.1.","severity":{"version":"3.1","score":8.1,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:H/A:H","level":"high","assessor":"cna","from":"cve"},"epss":{"day":"2026-11-09","score":0.00492,"percentile":0.42591,"model":"v2026.06.15"},"facts":{"in_kev":false,"known_exploited":false,"public_exploit":false,"fix_available":true},"cwes":["CWE-22"],"published":"2026-07-08T20:33:57Z","modified":"2026-10-28T02:31:03Z","fixes":[{"ecosystem":"PyPI","package":"asyncssh","fixed_in":["2.23.1"],"sources":["ghsa","osv"]},{"ecosystem":"Debian:14","package":"python-asyncssh","fixed_in":["2.24.0-1"],"sources":["osv"]}],"affected":[{"source":"ghsa","ecosystem":"PyPI","package":"asyncssh","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"last_affected":"2.23.0"},{"fixed":"2.23.1"}]}]},{"source":"osv","ecosystem":"Debian:12","package":"python-asyncssh","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["2.10.1-2","2.10.1-2+deb12u1","2.10.1-2+deb12u2","2.15.0-1","2.16.0-1","2.17.0-1","2.17.0-2","2.18.0-1","2.19.0-1","2.20.0-1","2.21.0-1","2.21.1-1","2.22.0-1","2.22.0-2","2.23.0-1","2.24.0-1","2.24.0-2"]},{"source":"osv","ecosystem":"Debian:13","package":"python-asyncssh","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["2.20.0-1","2.21.0-1","2.21.1-1","2.22.0-1","2.22.0-2","2.23.0-1","2.24.0-1","2.24.0-2"]},{"source":"osv","ecosystem":"Debian:14","package":"python-asyncssh","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"2.24.0-1"}]}],"versions":["2.20.0-1","2.21.0-1","2.21.1-1","2.22.0-1","2.22.0-2","2.23.0-1"]},{"source":"osv","ecosystem":"PyPI","package":"asyncssh","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"2.23.1"}]}],"versions":["0.8.1","0.8.2","0.8.3","0.8.4","0.9.0","0.9.1","0.9.2","1.0.0","1.0.1","1.1.0","1.1.1","1.10.0","1.10.1","1.11.0","1.11.1","1.12.0","1.12.1","1.12.2","1.13.0","1.13.1","1.13.2","1.13.3","1.14.0","1.15.0","1.15.1","1.16.0","1.16.1","1.17.0","1.17.1","1.18.0","1.2.0","1.2.1","1.3.0","1.3.1","1.3.2","1.4.0","1.4.1","1.5.0","1.5.1","1.5.2","1.5.3","1.5.4","1.5.5","1.5.6","1.6.0","1.6.1","1.6.2","1.7.1","1.7.2","1.7.3","1.8.0","1.8.1","1.9.0","2.0.0","2.0.1","2.1.0","2.10.0","2.10.1","2.11.0","2.12.0","2.13.0","2.13.1","2.13.2","2.14.0","2.14.1","2.14.2","2.15.0","2.16.0","2.17.0","2.18.0","2.19.0","2.2.0","2.2.1","2.20.0","2.21.0","2.21.1","2.22.0","2.23.0","2.3.0","2.4.0","2.4.1","2.4.2","2.5.0","2.6.0","2.7.0","2.7.1","2.7.2","2.8.0","2.8.1","2.9.0"]},{"source":"osv","ecosystem":"PyPI","package":"asyncssh","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"2.23.1"}]}],"versions":["0.8.1","0.8.2","0.8.3","0.8.4","0.9.0","0.9.1","0.9.2","1.0.0","1.0.1","1.1.0","1.1.1","1.10.0","1.10.1","1.11.0","1.11.1","1.12.0","1.12.1","1.12.2","1.13.0","1.13.1","1.13.2","1.13.3","1.14.0","1.15.0","1.15.1","1.16.0","1.16.1","1.17.0","1.17.1","1.18.0","1.2.0","1.2.1","1.3.0","1.3.1","1.3.2","1.4.0","1.4.1","1.5.0","1.5.1","1.5.2","1.5.3","1.5.4","1.5.5","1.5.6","1.6.0","1.6.1","1.6.2","1.7.1","1.7.2","1.7.3","1.8.0","1.8.1","1.9.0","2.0.0","2.0.1","2.1.0","2.10.0","2.10.1","2.11.0","2.12.0","2.13.0","2.13.1","2.13.2","2.14.0","2.14.1","2.14.2","2.15.0","2.16.0","2.17.0","2.18.0","2.19.0","2.2.0","2.2.1","2.20.0","2.21.0","2.21.1","2.22.0","2.23.0","2.3.0","2.4.0","2.4.1","2.4.2","2.5.0","2.6.0","2.7.0","2.7.1","2.7.2","2.8.0","2.8.1","2.9.0"]},{"source":"osv","ecosystem":"Ubuntu:16.04:LTS","package":"python-asyncssh","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["1.2.0-1","1.2.1-1","1.3.0-1"]},{"source":"osv","ecosystem":"Ubuntu:Pro:18.04:LTS","package":"python-asyncssh","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["1.8.1-2","1.11.0-2","1.11.1-1","1.11.1-1ubuntu0.1~esm1","1.11.1-1ubuntu0.1~esm2"]},{"source":"osv","ecosystem":"Ubuntu:20.04:LTS","package":"python-asyncssh","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["1.12.2-1","1.12.2-1ubuntu0.1","1.12.2-1ubuntu0.2"]},{"source":"osv","ecosystem":"Ubuntu:Pro:22.04:LTS","package":"python-asyncssh","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["2.5.0-1","2.5.0-1ubuntu0.1~esm1","2.5.0-1ubuntu0.1","2.5.0-1ubuntu0.1+esm1"]},{"source":"osv","ecosystem":"Ubuntu:Pro:24.04:LTS","package":"python-asyncssh","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["2.10.1-2","2.10.1-2ubuntu0.1","2.10.1-2ubuntu0.1+esm1"]},{"source":"osv","ecosystem":"Ubuntu:25.10","package":"python-asyncssh","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["2.20.0-1"]},{"source":"osv","ecosystem":"Ubuntu:26.10","package":"python-asyncssh","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["2.21.1-1","2.23.0-1"]},{"source":"osv","ecosystem":"Ubuntu:26.04:LTS","package":"python-asyncssh","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["2.20.0-1","2.21.1-1"]}],"products":[{"vendor":"ronf","product":"asyncssh"}],"references":[{"url":"https://github.com/ronf/asyncssh/security/advisories/GHSA-2wxc-x7rj-hg8f","tags":["x_refsource_CONFIRM","advisory","web","report"]},{"url":"https://github.com/ronf/asyncssh/commit/d730803b8e4e94c20c7580d90f94d1e05f9f58de","tags":["x_refsource_MISC","fix","web","report"]},{"url":"https://github.com/ronf/asyncssh/releases/tag/v2.23.1","tags":["x_refsource_MISC","web","report"]},{"url":"https://nvd.nist.gov/vuln/detail/CVE-2026-54591","tags":["advisory"]},{"url":"https://github.com/advisories/GHSA-2wxc-x7rj-hg8f","tags":["advisory"]},{"url":"https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/54xxx/CVE-2026-54591.json","tags":["advisory"]},{"url":"https://security-tracker.debian.org/tracker/CVE-2026-54591","tags":["advisory"]},{"url":"https://github.com/ronf/asyncssh","tags":["package"]},{"url":"https://pypi.org/project/asyncssh","tags":["package"]},{"url":"https://ubuntu.com/security/CVE-2026-54591","tags":["report"]},{"url":"https://www.cve.org/CVERecord?id=CVE-2026-54591","tags":["report"]}],"sources":{"cve":[{"id":"CVE-2026-54591","title":"AsyncSSH: SCP Path Traversal to Arbitrary File Write","description":"AsyncSSH is a Python package which provides an asynchronous client and server implementation of the SSHv2 protocol on top of the Python asyncio framework. Prior to 2.23.1, a malicious SSH server can write arbitrary files on the asyncssh SCP client's filesystem by sending filenames containing ../ traversal sequences because _parse_cd_args in scp.py returns server-provided names verbatim and _recv_files joins them to the destination path without enforcing the target directory boundary. This issue is fixed in version 2.23.1.","status":"published","published":"2026-07-08T20:33:57.42Z","modified":"2026-07-09T14:40:52.505Z","cvss":[{"version":"3.1","score":8.1,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:H/A:H","level":"high","assessor":"cna"}],"cwes":["CWE-22"],"updated_at":"2026-11-02T13:38:09.774038Z"}],"euvd":[{"id":"EUVD-2026-42399","description":"AsyncSSH is a Python package which provides an asynchronous client and server implementation of the SSHv2 protocol on top of the Python asyncio framework. Prior to 2.23.1, a malicious SSH server can write arbitrary files on the asyncssh SCP client's filesystem by sending filenames containing ../ traversal sequences because _parse_cd_args in scp.py returns server-provided names verbatim and _recv_files joins them to the destination path without enforcing the target directory boundary. This issue is fixed in version 2.23.1.","status":"published","published":"2026-07-08T20:33:57Z","modified":"2026-07-09T14:40:52Z","cvss":[{"version":"3.1","score":8.1,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:H/A:H","level":"high"}],"updated_at":"2026-11-02T18:20:04.126011Z"}],"ghsa":[{"id":"GHSA-2wxc-x7rj-hg8f","title":"asyncssh has SCP Path Traversal to Arbitrary File Write","description":"| | |\n|---|---|\n| Product | asyncssh (all versions through 2.23.0) |\n| Related | CVE-2019-6111 (same class in OpenSSH) |\n| Fix | AsyncSSH 2.23.1 |\n\nA 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/authorized_keys`, 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.\n\n---\n\n**Steps to exploit:**\n\n**Step 1 - Normal usage:** Application calls `await asyncssh.scp((conn, 'file'), '/home/user/downloads/')`. This is the standard, documented API.\n\n**Step 2 - SCP protocol:** asyncssh opens an SSH exec channel, runs `scp -f file`. The server controls the filename field:\n\n```\nC0644 100 ../pwned.txt\\n       (simple traversal)\n\nD0755 0 ..\\n                   (traverse up, repeat as needed)\nC0644 47 .bashrc\\n             (write payload)\nE\\n\n```\n\n**Step 3 - `_parse_cd_args`** (`scp.py:134-142`) returns the filename verbatim:\n\n```python\ndef _parse_cd_args(args: bytes) -\u003e Tuple[int, int, bytes]:\n    permissions, size, name = args.split(None, 2)\n    return int(permissions, 8), int(size), name  # no sanitization\n```\n\nThe returned `name` is not passed through `basename()` and is not checked for `..` or `/` components.\n\n**Step 4 - `_recv_files`** (`scp.py:706-713`) joins the unsanitized name:\n\n```python\nnew_dstpath = posixpath.join(dstpath, name)\n```\n\nWith `dstpath=b'/home/user/downloads/subdir'` and `name=b'../pwned.txt'`, this resolves to `/home/user/downloads/pwned.txt`, outside the target.\n\n**Step 5 - File write:** `_recv_file` 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.\n\n**Step 6 - RCE chains:**\n\n| Target | Execution trigger | Reliability |\n|---|---|---|\n| `~/.bashrc` | Next terminal open | High |\n| `~/.profile` | Next login | High |\n| `~/.ssh/rc` | Next SSH connection (requires sshd) | High |\n| `~/.ssh/authorized_keys` | Attacker logs in with `command=` | Medium |\n\n---\n\n**Reproduction:**\n\nLink to reproduction script: [path_traversal_poc.zip](https://github.com/user-attachments/files/28160665/path_traversal_poc.zip)\n\n```bash\ndocker build -t asyncssh-scp-traversal -f Dockerfile .\ndocker run --rm asyncssh-scp-traversal\n```\n\nThe attached `poc_scp_traversal.py` starts a malicious SSH server in-process using asyncssh's own API, then downloads from it via `asyncssh.scp()`.\n\n*Expected Output:*\n\n\u003cimg width=\"1400\" height=\"815\" alt=\"image\" src=\"https://github.com/user-attachments/assets/496745e4-d11d-4ed8-bddd-d15dd13d1751\" /\u003e","status":"published","published":"2026-08-26T15:34:22Z","modified":"2026-08-26T15:34:23Z","cvss":[{"version":"3.1","score":8.1,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:H/A:H","level":"high"}],"cwes":["CWE-22"],"updated_at":"2026-11-02T14:41:07.031507Z"}],"nvd":[{"id":"CVE-2026-54591","description":"AsyncSSH is a Python package which provides an asynchronous client and server implementation of the SSHv2 protocol on top of the Python asyncio framework. Prior to 2.23.1, a malicious SSH server can write arbitrary files on the asyncssh SCP client's filesystem by sending filenames containing ../ traversal sequences because _parse_cd_args in scp.py returns server-provided names verbatim and _recv_files joins them to the destination path without enforcing the target directory boundary. This issue is fixed in version 2.23.1.","status":"published","published":"2026-07-08T21:16:49.657Z","modified":"2026-10-25T17:10:00.197Z","cvss":[{"version":"3.1","score":8.1,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:H/A:H","level":"high","assessor":"secondary"}],"cwes":["CWE-22"],"updated_at":"2026-11-02T14:12:28.4135Z"}],"osv":[{"id":"CVE-2026-54591","title":"AsyncSSH: SCP Path Traversal to Arbitrary File Write","description":"AsyncSSH is a Python package which provides an asynchronous client and server implementation of the SSHv2 protocol on top of the Python asyncio framework. Prior to 2.23.1, a malicious SSH server can write arbitrary files on the asyncssh SCP client's filesystem by sending filenames containing ../ traversal sequences because _parse_cd_args in scp.py returns server-provided names verbatim and _recv_files joins them to the destination path without enforcing the target directory boundary. This issue is fixed in version 2.23.1.","status":"published","published":"2026-07-08T20:33:57.42Z","modified":"2026-10-28T02:31:03.317695231Z","cvss":[{"version":"3.1","score":8.1,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:H/A:H","level":"high"}],"cwes":["CWE-22"],"updated_at":"2026-11-02T15:45:10.818486Z"},{"id":"DEBIAN-CVE-2026-54591","description":"AsyncSSH is a Python package which provides an asynchronous client and server implementation of the SSHv2 protocol on top of the Python asyncio framework. Prior to 2.23.1, a malicious SSH server can write arbitrary files on the asyncssh SCP client's filesystem by sending filenames containing ../ traversal sequences because _parse_cd_args in scp.py returns server-provided names verbatim and _recv_files joins them to the destination path without enforcing the target directory boundary. This issue is fixed in version 2.23.1.","status":"published","published":"2026-07-08T21:16:49.657Z","modified":"2026-10-26T11:47:33.112391311Z","cvss":[{"version":"3.1","score":8.1,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:H/A:H","level":"high"}],"updated_at":"2026-11-02T15:45:57.236551Z"},{"id":"GHSA-2wxc-x7rj-hg8f","title":"asyncssh has SCP Path Traversal to Arbitrary File Write","description":"| | |\n|---|---|\n| Product | asyncssh (all versions through 2.23.0) |\n| Related | CVE-2019-6111 (same class in OpenSSH) |\n| Fix | AsyncSSH 2.23.1 |\n\nA 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/authorized_keys`, 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.\n\n---\n\n**Steps to exploit:**\n\n**Step 1 - Normal usage:** Application calls `await asyncssh.scp((conn, 'file'), '/home/user/downloads/')`. This is the standard, documented API.\n\n**Step 2 - SCP protocol:** asyncssh opens an SSH exec channel, runs `scp -f file`. The server controls the filename field:\n\n```\nC0644 100 ../pwned.txt\\n       (simple traversal)\n\nD0755 0 ..\\n                   (traverse up, repeat as needed)\nC0644 47 .bashrc\\n             (write payload)\nE\\n\n```\n\n**Step 3 - `_parse_cd_args`** (`scp.py:134-142`) returns the filename verbatim:\n\n```python\ndef _parse_cd_args(args: bytes) -\u003e Tuple[int, int, bytes]:\n    permissions, size, name = args.split(None, 2)\n    return int(permissions, 8), int(size), name  # no sanitization\n```\n\nThe returned `name` is not passed through `basename()` and is not checked for `..` or `/` components.\n\n**Step 4 - `_recv_files`** (`scp.py:706-713`) joins the unsanitized name:\n\n```python\nnew_dstpath = posixpath.join(dstpath, name)\n```\n\nWith `dstpath=b'/home/user/downloads/subdir'` and `name=b'../pwned.txt'`, this resolves to `/home/user/downloads/pwned.txt`, outside the target.\n\n**Step 5 - File write:** `_recv_file` 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.\n\n**Step 6 - RCE chains:**\n\n| Target | Execution trigger | Reliability |\n|---|---|---|\n| `~/.bashrc` | Next terminal open | High |\n| `~/.profile` | Next login | High |\n| `~/.ssh/rc` | Next SSH connection (requires sshd) | High |\n| `~/.ssh/authorized_keys` | Attacker logs in with `command=` | Medium |\n\n---\n\n**Reproduction:**\n\nLink to reproduction script: [path_traversal_poc.zip](https://github.com/user-attachments/files/28160665/path_traversal_poc.zip)\n\n```bash\ndocker build -t asyncssh-scp-traversal -f Dockerfile .\ndocker run --rm asyncssh-scp-traversal\n```\n\nThe attached `poc_scp_traversal.py` starts a malicious SSH server in-process using asyncssh's own API, then downloads from it via `asyncssh.scp()`.\n\n*Expected Output:*\n\n\u003cimg width=\"1400\" height=\"815\" alt=\"image\" src=\"https://github.com/user-attachments/assets/496745e4-d11d-4ed8-bddd-d15dd13d1751\" /\u003e","status":"published","published":"2026-08-26T15:34:22Z","modified":"2026-09-10T12:25:50.570417065Z","cvss":[{"version":"3.1","score":8.1,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:H/A:H","level":"high"}],"cwes":["CWE-22"],"updated_at":"2026-11-02T15:46:35.050232Z"},{"id":"PYSEC-2026-3808","title":"asyncssh has SCP Path Traversal to Arbitrary File Write","description":"| | |\n|---|---|\n| Product | asyncssh (all versions through 2.23.0) |\n| Related | CVE-2019-6111 (same class in OpenSSH) |\n| Fix | AsyncSSH 2.23.1 |\n\nA 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/authorized_keys`, 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.\n\n---\n\n**Steps to exploit:**\n\n**Step 1 - Normal usage:** Application calls `await asyncssh.scp((conn, 'file'), '/home/user/downloads/')`. This is the standard, documented API.\n\n**Step 2 - SCP protocol:** asyncssh opens an SSH exec channel, runs `scp -f file`. The server controls the filename field:\n\n```\nC0644 100 ../pwned.txt\\n       (simple traversal)\n\nD0755 0 ..\\n                   (traverse up, repeat as needed)\nC0644 47 .bashrc\\n             (write payload)\nE\\n\n```\n\n**Step 3 - `_parse_cd_args`** (`scp.py:134-142`) returns the filename verbatim:\n\n```python\ndef _parse_cd_args(args: bytes) -\u003e Tuple[int, int, bytes]:\n    permissions, size, name = args.split(None, 2)\n    return int(permissions, 8), int(size), name  # no sanitization\n```\n\nThe returned `name` is not passed through `basename()` and is not checked for `..` or `/` components.\n\n**Step 4 - `_recv_files`** (`scp.py:706-713`) joins the unsanitized name:\n\n```python\nnew_dstpath = posixpath.join(dstpath, name)\n```\n\nWith `dstpath=b'/home/user/downloads/subdir'` and `name=b'../pwned.txt'`, this resolves to `/home/user/downloads/pwned.txt`, outside the target.\n\n**Step 5 - File write:** `_recv_file` 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.\n\n**Step 6 - RCE chains:**\n\n| Target | Execution trigger | Reliability |\n|---|---|---|\n| `~/.bashrc` | Next terminal open | High |\n| `~/.profile` | Next login | High |\n| `~/.ssh/rc` | Next SSH connection (requires sshd) | High |\n| `~/.ssh/authorized_keys` | Attacker logs in with `command=` | Medium |\n\n---\n\n**Reproduction:**\n\nLink to reproduction script: [path_traversal_poc.zip](https://github.com/user-attachments/files/28160665/path_traversal_poc.zip)\n\n```bash\ndocker build -t asyncssh-scp-traversal -f Dockerfile .\ndocker run --rm asyncssh-scp-traversal\n```\n\nThe attached `poc_scp_traversal.py` starts a malicious SSH server in-process using asyncssh's own API, then downloads from it via `asyncssh.scp()`.\n\n*Expected Output:*\n\n\u003cimg width=\"1400\" height=\"815\" alt=\"image\" src=\"https://github.com/user-attachments/assets/496745e4-d11d-4ed8-bddd-d15dd13d1751\" /\u003e","status":"published","published":"2026-09-10T09:44:57.655635Z","modified":"2026-09-10T12:15:06.100986067Z","cvss":[{"version":"3.1","score":8.1,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:H/A:H","level":"high"}],"updated_at":"2026-11-02T15:52:57.255153Z"},{"id":"UBUNTU-CVE-2026-54591","description":"AsyncSSH is a Python package which provides an asynchronous client and server implementation of the SSHv2 protocol on top of the Python asyncio framework. Prior to 2.23.1, a malicious SSH server can write arbitrary files on the asyncssh SCP client's filesystem by sending filenames containing ../ traversal sequences because _parse_cd_args in scp.py returns server-provided names verbatim and _recv_files joins them to the destination path without enforcing the target directory boundary. This issue is fixed in version 2.23.1.","status":"published","published":"2026-07-08T21:16:00Z","modified":"2026-10-17T12:59:07.121627826Z","cvss":[{"version":"3.1","score":8.1,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:H/A:H","level":"high"}],"updated_at":"2026-11-02T16:56:41.382716Z"}]}}
