A keyless lock that opens when you jiggle the handle with a very long password
OpenSSH before 10.6p2 has an authentication bypass when built against musl libc with UsePAM no — the exact configuration used by Alpine Linux's default openssh-server package. When sshd verifies a password, it calls musl's crypt(). If the supplied password is 256–1024 characters, musl returns * as an error sentinel, and sshd then compares that * against the stored password hash for accounts that have no password set (*). The strings match, and the login succeeds. Affected versions: OpenSSH 0 through <10.6p2 on musl/no-PAM Linux, fixed in 10.6p2.
Vendor severity HIGH (8.1) overstates the real exposure because the vulnerable population is narrow: only musl/no-PAM systems, and only accounts whose password field is * and whose shell allows SSH login. glibc distros (Debian, Ubuntu, RHEL) and sshd with PAM enabled are not affected. On most production systems, root is blocked by PermitRootLogin prohibit-password and service accounts have /sbin/nologin, so the practical default exploitability is lower than 'remote unauth root'.
4 steps from start to impact.
Find exposed sshd on a musl Linux host
- Network access to the SSH port
- OpenSSH <10.6p2 on musl/no-PAM
- Most enterprise Linux is glibc and unaffected
- SSH is often restricted to VPN/jump-host segments
SSH weak auth.Confirm vulnerable sshd configuration
UsePAM no and PasswordAuthentication yes by attempting a long-password login or by using research tools; a valid account with a real password will reject the long password, but a * account will accept it. No scanner method reliably reports config without shell access, so the attacker may simply try candidate accounts.UsePAM noandPasswordAuthentication yes- Account with stored password hash
*and valid shell
- Hardened baselines disable password auth
- Root is usually blocked by
PermitRootLogin prohibit-password
awk -F: '$2=="*" && $7 !~ /(nologin|false)/{print $1}' /etc/shadow identifies candidates.Send a 256–1024 character password
ssh, Paramiko, sshpass) is given a long password. musl's crypt() returns * for passwords longer than 256 bytes, matching the * hash for a no-password account. The login succeeds without knowing any actual credential.- Password length 256–1024 bytes
- No account lockout or MaxAuthTries limit reached
- This step is trivial; the difficulty is entirely in the preceding preconditions
Obtain shell access as the bypassed account
- Valid login shell on the account
- Account permitted by AllowUsers/DenyUsers/DenyGroups
- Service accounts often have
/sbin/nologinor/bin/false - Non-root account may have limited privileges
apk upgrade -U -a) and restart sshd — This removes the crypt() comparison flaw. Remediate within 365 days under the noisgate remediation SLA for MEDIUM; no mitigation SLA applies, but affected Alpine hosts with no-password accounts should be prioritized in the patch cycle.PasswordAuthentication in /etc/ssh/sshd_config and restart sshd — Immediately blocks the attack path if you cannot patch yet. Ensure working pubkey access first. Under MEDIUM there is no mitigation SLA, but this can be done at the next change window or immediately on high-risk hosts./etc/shadow for accounts with * password field and valid shells; lock or assign passwords — Removes the account precondition. Use awk -F: '$2=="*" && $7 !~ /(nologin|false)/{print $1}' /etc/shadow. For service accounts run passwd -l <user> or usermod -s /sbin/nologin <user>.- Enabling
UsePAM yeson Alpine without testing often breaks sshd authentication or is unavailable in minimal musl builds; it is not a drop-in mitigation. - Fail2ban/account lockout won't help because the attacker succeeds on the first attempt with any long password, and the account may not have failed logins.
- Replacing musl
crypt()behavior locally is not a user-level mitigation; source patch or vendor package is required.
The supporting signals.
| In-the-wild status | No known exploitation in the wild; CISA KEV not listed as of 2026-11-05. |
|---|---|
| PoC availability | Trivially reproducible; IONIX reports public reproduction labs. No weaponized PoC, Nuclei template, or OpenVAS check yet per cve.tools. |
| EPSS score | No EPSS score available; early prediction not yet published. |
| KEV status | Not in CISA KEV (as of 2026-11-05). |
| CVSS vector | CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H — AC:H reflects the narrow preconditions, but C/I/A assume the bypassed account is high-privilege; usually it isn't. |
| Affected versions | OpenSSH < 10.6p2 on Linux with musl libc and UsePAM no; canonical platform is Alpine Linux openssh-server. |
| Fixed versions | OpenSSH 10.6p2; Alpine patched packages on supported branches via apk upgrade -U -a. |
| Scanning/exposure data | IONIX flags SSH services that accept password login as SSH weak auth; no public GreyNoise/Shodan/Censys aggregate for this specific CVE yet. |
| Disclosure date | 2026-11-05. |
| Reporting researcher/org | Rich Felker (musl advisory); MITRE CNA; IONIX named SSHHole. |
Sources.
Why this verdict
- Friction: musl/no-PAM narrows the install base from all OpenSSH to a minority of Alpine/musl Linux deployments. Baseline 8.1 is fair only for that subset; enterprise glibc/PAM builds are unaffected, so the baseline applies to a niche.
- Friction: the account precondition further shrinks the vulnerable population. Only accounts whose
/etc/shadowpassword field is*and whose shell is a valid login shell are bypassable. Root is normally blocked byPermitRootLogin prohibit-password, and most service accounts have/sbin/nologin. - Role multiplier: no high-value-role floor is triggered. Canonical high-value roles (IdP, AD, CA, PAM, hypervisor, CI/CD, backup, SIEM, edge) overwhelmingly run glibc or FreeBSD and are unaffected; affected OpenSSH-on-musl installs are predominantly Alpine VMs/containers in low/typical roles. If an Alpine edge appliance did have a no-password account, the chain would yield perimeter host compromise, but such installs are well under 1% of the impacted population, so no floor applies.
- Impact downgrade: CVSS assumes
C:H/I:H/A:H(compromised account equals host/domain compromise), but the realistic bypassed account is unprivileged, making the practical impact closer toC:L/I:L/A:Lor at mostC:Honly after a separate local privilege escalation.
Why not higher?
Not higher because the vulnerability requires the intersection of OpenSSH <10.6p2, musl libc, UsePAM no, PasswordAuthentication yes, and an account with a * password hash plus valid shell. That is rare in production. glibc/PAM systems are unaffected, and the default root account is usually shielded by PermitRootLogin prohibit-password.
Why not lower?
Not lower because when those preconditions exist, the attacker gets an unauthenticated remote shell with a single scripted login and no credential guessing. Alpine's default openssh-server is affected in its default configuration if a no-password account exists, and the fix is a standard package upgrade; leaving exposed hosts unpatched creates an easy foothold.
Crowdsourced verification payload.
Run this bash script on each Alpine/musl Linux host where OpenSSH sshd is installed, as root (needed to read /etc/shadow and run sshd -T). Invocation: bash cve-2026-123158_check.sh. It prints VULNERABLE, PATCHED, or UNKNOWN and exits 0/1/3.
#!/bin/bash
# CVE-2026-123158 check: OpenSSH <10.6p2 + musl + UsePAM no + PasswordAuthentication yes + no-password account with shell
set -u
SSHD_BIN="$(command -v sshd || true)"
if [ -z "$SSHD_BIN" ] || [ ! -x "$SSHD_BIN" ]; then
echo "UNKNOWN: sshd not found"
exit 3
fi
# 1. Check libc
if ! ldd "$SSHD_BIN" 2>/dev/null | grep -q musl; then
echo "PATCHED: not musl-linked (glibc or non-musl build)"
exit 0
fi
# 2. Check version < 10.6.2 (OpenSSH_10.6p2)
full_ver="$($SSHD_BIN -V 2>&1 | head -1 | sed -n 's/OpenSSH_\([0-9][^ ,]*\).*/\1/p')"
if [ -z "$full_ver" ]; then
echo "UNKNOWN: cannot parse sshd version"
exit 3
fi
if awk -v v="$full_ver" 'BEGIN { split(v,a,"[p.]"); split("10.6.2",b,"[p.]"); for(i=1;i<=3;i++){ if ((a[i]+0) < (b[i]+0)) exit 1; if ((a[i]+0) > (b[i]+0)) exit 0; } exit 0 }'; then
echo "PATCHED: sshd version $full_ver is >= 10.6.2"
exit 0
fi
# 3. Check sshd effective configuration
if ! conf="$($SSHD_BIN -T 2>/dev/null)"; then
echo "UNKNOWN: cannot read sshd effective config (run as root)"
exit 3
fi
usepam="$(echo "$conf" | awk '$1=="usepam"{print $2}')"
passauth="$(echo "$conf" | awk '$1=="passwordauthentication"{print $2}')"
if [ "$usepam" != "no" ]; then
echo "PATCHED: UsePAM is '$usepam' (not no)"
exit 0
fi
if [ "$passauth" != "yes" ]; then
echo "PATCHED: PasswordAuthentication is '$passauth' (not yes)"
exit 0
fi
# 4. Look for a locked/no-password account with a valid shell
vuln_account=""
while IFS=: read -r user pass uid gid gecos home shell; do
if [ "$pass" = "*" ] && [ -n "$shell" ] && ! echo "$shell" | grep -Eq '/(nologin|false)$'; then
vuln_account="$user"
break
fi
done < /etc/shadow
if [ -z "$vuln_account" ]; then
echo "PATCHED: no locked/no-password account with valid shell found"
exit 0
fi
echo "VULNERABLE: sshd $full_ver on musl, UsePAM no, PasswordAuthentication yes, account '$vuln_account' has * password with shell $shell"
exit 1