CVE-2026-45309 Overview
CVE-2026-45309 is a path traversal vulnerability [CWE-22] in AsyncSSH, a Python package providing an asynchronous SSHv2 client and server implementation built on the Python asyncio framework. Versions prior to 2.23.0 expand the OpenSSH-compatible AuthorizedKeysFile %u token with the raw SSH username during pre-authentication server config reload. An attacker can supply a username containing /, \, or .. path traversal segments to redirect the authorized-keys lookup outside the intended directory. The attacker can then authenticate with a key file of their choosing. The issue is fixed in AsyncSSH 2.23.0.
Critical Impact
Remote attackers can bypass SSH authentication on servers configured with AuthorizedKeysFile authorized_keys/%u by supplying a crafted username that traverses to an attacker-controlled key file.
Affected Products
- AsyncSSH Python package versions prior to 2.23.0
- SSH server deployments using AuthorizedKeysFile templates that include the %u token
- Applications embedding AsyncSSH server functionality with per-user authorized key file layouts
Discovery Timeline
- 2026-07-17 - CVE-2026-45309 published to NVD
- 2026-07-23 - Last updated in NVD database
Technical Details for CVE-2026-45309
Vulnerability Analysis
AsyncSSH mirrors OpenSSH configuration semantics, including token substitution inside AuthorizedKeysFile. The %u token is intended to expand to the authenticating user's name, producing a per-user path such as authorized_keys/alice. AsyncSSH performs this substitution in asyncssh/config.py, asyncssh/connection.py, asyncssh/auth_keys.py, and asyncssh/misc.py during pre-authentication server config reload. The substitution uses the raw username string without validating for path separators, drive letters, or parent-directory segments. As a result, the resolved file path can escape the intended directory when the SSH client presents a specially crafted username.
Root Cause
The underlying defect is missing input validation on the SSH username before it is interpolated into a filesystem path [CWE-22]. Because token expansion happens prior to authentication, the server trusts an attacker-supplied identifier to compose a security-critical file lookup. Usernames containing /, \, .., or Windows drive prefixes such as C: are treated as legitimate path fragments.
Attack Vector
An unauthenticated remote attacker connects to a vulnerable AsyncSSH server and presents a username such as ../../tmp/attacker. The server expands AuthorizedKeysFile authorized_keys/%u into a path outside the intended directory. If the attacker can place a public key file at that resolved location, either through a separate write primitive, a shared filesystem, or a world-writable directory, they can then authenticate using the matching private key.
# Security patch in asyncssh/config.py
# Source: https://github.com/ronf/asyncssh/commit/3d515ba9ba0cd9990d248bdf62bcf05d51261a88
_token_pattern = re.compile(r'%(.)')
_env_pattern = re.compile(r'\${(.*?)}')
_unsafe_user_pattern = re.compile(r'^\.\.$|^~|^[A-Za-z]:|[/\\]|\$\{.*?\}')
The added _unsafe_user_pattern regex rejects usernames that are .., begin with ~ or a drive letter, contain forward or backward slashes, or embed environment variable references. A companion commit introduced the IllegalUserName exception surfaced during unsafe substitution.
Detection Methods for CVE-2026-45309
Indicators of Compromise
- SSH authentication log entries containing usernames with /, \, .., ~, or drive letter prefixes such as C:
- Successful authentications for users that do not exist in the system identity store
- Access to authorized_keys files located outside the configured base directory
- Unexpected reads of files whose paths resolve above the AsyncSSH working directory
Detection Strategies
- Inspect AsyncSSH server logs for pre-authentication username strings containing path traversal characters and alert on any non-alphanumeric username tokens.
- Enable filesystem auditing on the directory referenced by AuthorizedKeysFile and generate alerts for reads originating from the AsyncSSH process that resolve outside that directory.
- Correlate successful public-key authentications with the resolved key file path to identify lookups that escape the intended per-user layout.
Monitoring Recommendations
- Ship AsyncSSH connection logs to a centralized logging pipeline and apply detections for suspicious username patterns.
- Track the installed AsyncSSH package version across Python environments and flag any host running a release earlier than 2.23.0.
- Monitor for new or modified authorized_keys files appearing in unexpected filesystem locations that could be staged for exploitation.
How to Mitigate CVE-2026-45309
Immediate Actions Required
- Upgrade AsyncSSH to version 2.23.0 or later in every Python environment that hosts an SSH server.
- Audit AsyncSSH server configurations for AuthorizedKeysFile directives containing the %u token and confirm they resolve only within an intended directory.
- Review recent SSH authentication logs for usernames containing path traversal characters and rotate any keys associated with suspicious sessions.
Patch Information
The fix is available in AsyncSSH 2.23.0. Two commits address the issue: commit 2af2382 introduces the IllegalUserName exception for unsafe user substitutions, and commit 3d515ba expands the unsafe username regex to cover slashes, drive letters, tilde prefixes, and embedded environment expansions. See the GitHub Security Advisory GHSA-g794-3fmp-753h for the full advisory.
Workarounds
- Remove the %u token from AuthorizedKeysFile and use a single shared authorized keys file with per-key restrictions until the upgrade is complete.
- Enforce a strict username allowlist in an upstream layer, rejecting any connection whose username contains characters outside [A-Za-z0-9_-].
- Run the AsyncSSH server under a dedicated unprivileged account with filesystem access restricted to the intended authorized-keys directory to limit the reach of traversal attempts.
# Configuration example: upgrade AsyncSSH and validate the installed version
pip install --upgrade 'asyncssh>=2.23.0'
python -c "import asyncssh; print(asyncssh.__version__)"
# Safer AuthorizedKeysFile layout without the %u token
# AuthorizedKeysFile /etc/asyncssh/authorized_keys
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

