Overview
OpenSSH released 10.6p2 on November 5, 2026 with what its release notes call "a critical security workaround" for a password authentication bypass: on affected systems, a remote attacker can log in over SSH without knowing any password. It affects Linux systems that use the musl C library and run sshd without PAM — Alpine Linux (opens in a new tab) in practice. Where the root cause lies is disputed: OpenSSH says it's "outside sshd" but "exploitable via sshd and can be avoided there," so 10.6p2 avoids it, while musl's maintainer, Rich Felker, says "this is not a bug in musl just an erroneous use by the caller" — though he adds musl will likely change the behavior anyway. Either way, the trigger is how musl's crypt() signals an error, reached through sshd's own password check. No CVE has been assigned, and there is no CVSS score: OpenSSH calls it critical in its release notes, and Alpine's advisory gives no rating of its own. The bug was reported by Özgün Kültekin of Wakefield.
Why it's urgent: sshd is reachable from the network by design, the attack needs one connection with no retries, and the preconditions are ordinary — one account with a password, plus a key-only account whose name the attacker needs, though names like root or alpine are predictable. Alpine is one of the most common base images for containers and small VPS hosts, though most containers don't run sshd. The fix reaches Alpine with a normal upgrade, but the running daemon keeps the flaw until it restarts. Technical details are already public, including the reporter's *sshole write-up (opens in a new tab), so treat internet-exposed hosts as urgent.
Key facts
| Field | Detail |
|---|---|
| Identifier | None. OpenSSH shipped the fix in 10.6p2; no CVE had been assigned as of 10:00 AM CST, November 5, and neither OpenSSH's notes nor Alpine's advisory carry a CVSS score |
| Severity | Critical, OpenSSH's own word in its release notes. Alpine's advisory assigns no rating, and no numeric score exists yet |
| Root cause | Disputed. OpenSSH places it "outside sshd" and still blocks it; musl's maintainer says it's "not a bug in musl just an erroneous use by the caller." The collision is in how musl's crypt() signals an error, reached through sshd's password check when it runs without PAM |
| Impact | A remote, unauthenticated attacker logs in as a key-only account. root is reachable only if PermitRootLogin yes is set, because the default prohibit-password protects it |
| Affected | A musl system running sshd without PAM, with PasswordAuthentication yes, at least one account whose password field is *, and at least one account with a $5$ or $6$ hash |
| Fixed in | OpenSSH 10.6p2; Alpine packages from 10.6_p2-r0 (edge) down to 9.0_p1-r6 (3.16) — see the table below |
| Not affected | glibc systems, any system using PAM for password auth, non-Linux systems, and Dropbear |
| Credit | Reported by Özgün Kültekin of Wakefield. Fixed by Damien Miller and Darren Tucker; Timo Teräs helped analyze it, and Natanael Copa built Alpine's packages |
Who is affected
A machine is affected only when every one of these is true, per Alpine's advisory (opens in a new tab):
- It uses the musl C library (Alpine and other musl distributions), not glibc.
sshdruns without PAM: Alpine'sopenssh-serverpackage is built without it, andopenssh-server-pamis built with PAM but still runs without it whenUsePAM nois set. Onlyopenssh-server-pamwithUsePAM yesis not affected.PasswordAuthenticationis yes, the OpenSSH default.- An account exists whose password field is
*— the normal marker for an account with no password, such as a key-only user, directory-service users with no shadow entry, androoton Alpine (shipped asroot:*since about 3.16). - At least one local account has a real
$5$or$6$password hash. Without one, the bug doesn't trigger.
That last condition is why Alpine's official container image isn't exposed on its own: root is * — we checked 3.21 through 3.24 — and no account has a hash yet. That changes the moment any account gets a password, whether an admin sets one or an image adds a user with a hashed password. Any host with a password hash and a * account meets the condition. Alpine calls out its tiny-cloud images, whose alpine user ships as * with passwordless doas: safe on first boot, exposed as soon as any hash exists, and then an attacker who logs in as alpine can doas to root.
Not affected: glibc systems; systems with PasswordAuthentication no; openssh-server-pam with UsePAM yes; accounts locked with ! (they can't log in at all); machines where no account has a $-style hash; images configured by cloud-init, which writes PasswordAuthentication no; and Dropbear, which hands the stored * to crypt() as the salt directly and so never gets a * back to match (we confirmed this on musl); Felker's advisory also lists Dropbear as unaffected. Containers that don't run sshd aren't affected.
Distribution status
Alpine has published fixed packages for every branch it still updates and for several that it doesn't. As of 10:00 AM CST, November 5:
Alpine Linux
FixedTracker- edgeFixed
10.6_p2-r0Nov 5 - 3.24Fixed
10.3_p1-r2Nov 5 - 3.23Fixed
10.2_p1-r1Nov 5 - 3.22Fixed
10.0_p1-r11Nov 5 - 3.21End of support Nov 1Fixed
9.9_p2-r1Nov 5 - 3.16 – 3.20No longer regularly updatedFixed anywayDown to 9.0_p1-r6 on 3.16Nov 5
The fix installs with a normal upgrade; we confirmed the 3.21 repository now serves the fixed 9.9_p2-r1. Restart sshd afterward; the package upgrade doesn't. See End-of-life versions for 3.16 through 3.21.
Other musl systems
The condition is musl plus sshd without PAM, so it isn't unique to Alpine. Other musl-based systems — Void Linux's musl variant, Chimera Linux, postmarketOS, Buildroot or Yocto images built with musl, and OpenWrt devices that run OpenSSH instead of Dropbear — should check whether they ship sshd at all and, if so, whether PAM is in use, using the checks below. We haven't confirmed a fix state for any of them; watch each project's own advisories. glibc distributions are not affected: Debian, Ubuntu, RHEL and their families, and Wolfi and Chainguard's images, which use glibc rather than musl.
How the vulnerability works
When sshd runs without PAM, it checks a password itself: it runs your attempt through the C library's crypt() function and compares the result to the account's stored password field. An account with no password stores a literal * in that field, which is not a valid hash, so no ordinary password should ever match it.
The flaw is a collision between two unrelated uses of the same *. Alpine's advisory explains that musl's crypt() returns the string * as its error value when the supplied key is longer than 256 bytes. OpenSSH accepts passwords up to 1024 bytes, so an attempt above that 256-byte boundary makes musl's crypt() return * — which is exactly what a no-password account already stores. The computed value and the stored value are both *, they compare equal, and sshd treats the password as correct. Nothing about the account's real credentials is involved; the match is an accident of how musl signals the error — it returns a short string rather than failing with NULL, and here that string equals the stored field. (The one account with a real hash matters because sshd needs a valid salt to hash against for the empty account; beyond supplying that, its password is never used.) We reproduced musl's behavior directly: crypt() returns * for an over-long key only when it's given a real account's salt, which is why the bug needs that second account.
This depends on OpenSSH's particular habit of hashing the attempt against another account's salt, so it doesn't generalize to every password check on musl. Felker's advisory says "Dropbear and other non-OpenSSH software using password-based logins is not affected," which matches our own Dropbear test. OpenSSH blocks it regardless of whose bug it is, and Alpine's stable-branch packages carry a patch for the same problem.
The fix
OpenSSH's change refuses to accept a match when the stored password field is too short to be a real hash. It adds a MIN_PASSWORD_HASH_LEN of 4 and requires the stored field to be at least that long before a comparison can succeed, so a one-byte * can never match whatever crypt() returns. The commit landed on the portable V_10_6 branch on November 4 and shipped in 10.6p2 the next day.
Which systems are exposed
What follows is our reading of the conditions in Alpine's advisory and OpenSSH's notes, not a confirmed login path for any one machine.
| Setup | Exposed? |
|---|---|
Alpine openssh-server (no PAM), PasswordAuthentication yes, a * account, one hashed account | Yes |
Same, but no account has a $5$/$6$ hash yet | Not yet: the bug needs one real hash present |
openssh-server-pam with UsePAM yes | No: PAM handles the password |
musl system with PasswordAuthentication no | No: sshd never runs the password check |
| glibc system (Debian, Ubuntu, RHEL, …), any config | No: the error-value collision is specific to musl's crypt() |
root with the default PermitRootLogin prohibit-password | Not as root directly; another * account that can log in and escalate still exposes the host |
| Dropbear, or other non-OpenSSH SSH servers | No: Felker's advisory says non-OpenSSH password logins aren't affected, and we confirmed Dropbear |
Patch first the musl hosts whose SSH port is reachable from untrusted networks, and any that have both a key-only account and an account with a password.
How to check your systems
A host's sshd and a container's sshd are separate, so check each one that runs it. We tested these in the official Alpine 3.21 image.
Check your C library and PAM
ldd --version 2>&1 | head -1 # "musl libc ..." means musl; "GLIBC" means glibcsshd -T | grep -i usepam # "usepam yes" = not affected; no line or "usepam no" = PAM not in usesshd -T | grep -i passwordauthenticationOn Alpine's default openssh-server, ldd reports musl libc, sshd -T prints no usepam line at all (it was compiled without PAM), and passwordauthentication yes unless you changed it — the exposed combination. The openssh-server-pam package with UsePAM no prints usepam no: PAM isn't handling the password there either, so it's exposed if the other conditions hold. A usepam yes host is not affected.
Check for the preconditions
# accounts with no password (field is *), which the bug can log in as:awk -F: '$2 == "*" { print $1 }' /etc/shadow# accounts with a $5$ or $6$ hash, one of which the bug needs present:awk -F: '$2 ~ /^\$[56]\$/ { print $1 }' /etc/shadowRun these as root. If the first list is non-empty and the second is too, the machine meets the conditions. In Alpine's official container image the second list is empty, which is why it isn't exposed until an account gets a password. One caveat: users that come from a directory service (via musl-nscd — nslcd, winbind, sssd) have no /etc/shadow entry, so this awk won't list them even though they count as * accounts.
How to fix
Update and restart sshd
On Alpine:
apk upgrade -U -arc-service sshd restartapk list --installed | grep -E '^openssh' # confirm the version (covers openssh-server-pam too)Alpine 3.21.10, 3.22.8, 3.23.8 and 3.24.4 carry the fixed package; the fixed versions per branch are in the table above. The restart matters: upgrading the package does not replace the running daemon, so sshd keeps the flaw until rc-service sshd restart. Rebuild container images on a fixed base, and rebuild anything built on alpine that runs sshd. If you build OpenSSH yourself, move to 10.6p2.
If you can't patch immediately
Turn off password authentication. This closes the hole on its own, because sshd then never runs the broken check:
mkdir -p /etc/ssh/sshd_config.decho 'PasswordAuthentication no' > /etc/ssh/sshd_config.d/00-no-passwords.confsshd -t && rc-service sshd restartsshd -T | grep -i passwordauthentication # should print: passwordauthentication noAlpine reads sshd_config.d from 3.19 onward; on older releases, set PasswordAuthentication no in /etc/ssh/sshd_config itself. Before you restart, make sure your key-based login already works and keep your current session open until you've tested a new one. Alpine's advisory has a longer sed recipe that also rewrites PasswordAuthentication yes lines inside Match blocks.
Check for signs of compromise
Alpine's advisory gives a forensic check. In /var/log/messages, look for sshd lines reading Accepted password for an account that has no password — root, the cloud images' alpine user, or any key-only user:
grep 'Accepted password' /var/log/messagesA password login for an account stored as * should be impossible, so one is a red flag. Review recent doas use, newly created users, and added authorized_keys on exposed hosts. If you can't rule a login out, treat the machine as compromised.
End-of-life versions
Alpine 3.21 reached end of support on November 1, 2026, and 3.16 through 3.20 are older still. Alpine published fixed openssh packages for all of them anyway, down to 9.0_p1-r6 on 3.16, so an apk upgrade plus an sshd restart fixes those hosts too. They remain unsupported for everything else; plan the upgrade to a current release.
Timeline
All times are US Central: CST (UTC−6).
- Fix
- Advisory or rating
- Nov 5
9:07 AMmusl's maintainer posts an advisory calling it "not a bug in musl just an erroneous use by the caller," and confirms Dropbear and other non-OpenSSH software aren't affected
OpenSSH releases 10.6p2 with the workaround, and Alpine publishes its advisory and fixed packages for every branch back to 3.16
- Nov 4
5:57 PMThe portable tree's version is bumped to 10.6p2
3:58 PMOpenSSH commits the workaround, "avoid password authn bypass," to the portable 10.6 branch
- Oct 6
OpenSSH 10.6/10.6p1 is released, without the fix
The notes carry the same statement OpenSSH has run since its October 6 release about why it's now shipping fixes faster: it has seen "a number of cases where a security bug identified by AI tools is subsequently independently discovered by a different researcher," which "suggests that adversaries who do not report bugs to OSS projects are likely to be able to discover these bugs too," so the team "will, for now, be making more frequent releases to get bugfixes into users' hands more quickly rather than batching them." This release is an instance of that: the fix was committed on November 4 and released the next day.
Updates to this post
We'll revise this post and mark it updated when any of these change: a CVE is assigned or an NVD entry appears; another musl distribution (Void, Chimera, postmarketOS, or a Buildroot/Yocto/OpenWrt build) publishes its own status; or a confirmed report of exploitation in the wild appears.
Get help
SSH is the account that reaches everything else, so it's worth knowing which of your hosts expose it and what else is listening. Our free security audit checks the domains and public IPs you verify for exposed services, publicly visible software versions with known CVEs, TLS, email security, DNS, and HTTP headers.
It's the second SSH disclosure we've covered in a month. The other was Tailscale's SSH and Serve vulnerabilities, also fixed without CVEs.
Sources
OpenSSH
- 10.6p2 release notes (opens in a new tab)openssh.com
- fix commit
90f9c2f(opens in a new tab)github.com - OpenSSH security page (opens in a new tab)openssh.com
Alpine Linux
musl
Researcher write-up
Background
- musl libc (opens in a new tab)musl.libc.org
- OpenSSH
sshd_configPasswordAuthentication(opens in a new tab)man.openbsd.org
The Atlas security byline: write-ups of vulnerabilities in widely deployed software — what changed, who is exposed, and what to check — verified against primary sources.