Alpine's *sshole Flaw Needs Four Conditions; Check Them, Then Restart sshd
A no-password account can open for any password over 256 bytes, but only on musl systems without PAM where a neighbour has a real hash. Here is the per-host triage, the patched versions and the restart that makes the fix real.
The safest kind of account on a Linux machine is the one with no password at all, because there is nothing to guess. On the wrong build, that account opens for any string of more than 256 bytes, provided a neighbouring account has a real password.
As of Friday morning, Nov. 6, the exposure comes down to four conditions, and all four must hold on the same host. It runs the SSH server, sshd, on the musl C library (a compact set of basic functions that programs borrow; Alpine Linux is its best-known home) without PAM, the add-on layer most Linux systems use to handle logins. Password logins are on, which is OpenSSH's default. Some account's password field holds nothing but a *. And at least one other account holds a real $5$ or $6$ password hash. Miss any one and the door stays shut. Per OpenSSH's Damien Miller, the flaw "does not exist on non-Linux systems, Linux/glibc systems and Linux systems that use PAM for password authentication," so Debian, Ubuntu and Fedora are out.
OpenSSH shipped an emergency release, 10.6p2, on Thursday, Nov. 5. The researcher who reported the hole, Özgün Kültekin of Wakefield, nicknamed it *sshole, a joke that only works because the asterisk is the whole story.
Four conditions, and one of them is a neighbour's password
Alpine's advisory is the careful document here, and it says what an attacker needs: the name of an account whose password field is *, and a password of 257 to 1,024 bytes. "It takes one connection, works every time, and needs no retries," the Alpine maintainers wrote.
The surprise is the neighbour. "One user with a password is enough: it makes every account without one reachable," the advisory says. One admin setting a console password arms every passwordless account on the box.
On a real Alpine host, which accounts hold a lone *? Root, for one: the base image has shipped root:* since about Alpine 3.16. Key-only users, created with adduser without a password or with usermod -p '*', are another. Users served by a directory service through musl-nscd, such as nslcd or sssd, have no shadow entry at all, and the alpine user in the official tiny-cloud images has a *, too. Locked accounts, marked ! in /etc/shadow, are a different matter and are not affected.
The cloud images deserve a second look. Alpine says tiny-cloud images (the qcow2, VHD and AMI files) from 3.18.11 through 3.24.3 ship an alpine user with a * and passwordless doas, Alpine's small sudo-like tool. They are "safe on first boot" and become exploitable once any $6$ hash exists, "for example when an admin sets a console password." Newer images carry the fix; on every running instance, update openssh or disable password authentication.
Now the root question. Root is protected by the default setting PermitRootLogin prohibit-password, so it is reachable only if someone set PermitRootLogin yes. Alpine adds the catch: that protection "does not help if another account that can log in is able to become root, for example through doas." The affected Alpine releases are 3.21 through 3.24 and edge, plus the older 3.16 to 3.20, which no longer get regular updates.
The CVE record, CVE-2026-123158, scores the flaw 8.1, High. CISA's entry, updated early Friday, lists exploitation as "poc" (proof of concept), not automatable, with total technical impact.
Two stars that meant different things
Without PAM, sshd takes the password you typed, runs it through a function called crypt(), and compares the result with the hash stored in the shadow file, the root-only file that holds every account's password data. A hash begins with a salt, a random prefix that makes identical passwords come out different. A lone * is far too short to carry one, so sshd borrows the salt from another account. That is the neighbour's job.
Here the two stars collide. musl's crypt() "returns the string * as an error indicator when the key is over 256 bytes long," as Alpine's advisory puts it. The shadow file's stored field is also *. The function says "I failed" and the file says "nothing here," and sshd, comparing one to the other, finds a match. The 1,024 ceiling is sshd's own limit.
No one step was foolish. Kültekin's write-up, retold by The Register, traces the * convention to 1980, when Bill Joy put an asterisk in the /etc/passwd entry for the daemon user. On Aug. 9, 2012, musl changed so a failed crypt() returns an unmatchable hash rather than a null that careless programs might ignore. Twenty days later, on Aug. 29, it capped keys at 256 bytes to stop slow, long-password hashing from knocking servers over. Then OpenSSH's July 15, 2016 fix for CVE-2016-6210, a flaw that revealed which usernames exist, made sshd borrow another account's salt. Kültekin says the problem has existed since then: 10 years, 3 months and 21 days before Nov. 5.
He found it by brute patience. Kültekin writes that he built sshd "every way I could think of (glibc, musl, pam, no pam, shadow, no shadow)" and threw "like 17,600 weird logins at it." His verdict: "every build agreed on every login. except musl without pam."
*sshole is out
— ozgun (@kultekin) November 5, 2026
if you run sshd on alpine, openwrt or any musl box with password auth on: update now
official writeup: https://t.co/hQUJXVPKwE https://t.co/KB6Nyz3dUo
Note the post's "openwrt." OpenWrt uses Dropbear, another SSH server, by default, and Kültekin says Dropbear is not affected, so a router matters only if an admin installed OpenSSH on it.
The headline numbers need the same care. Ars Technica's Dan Goodin notes that the Docker Hub base image for Alpine "has more than 1 billion downloads." But Alpine says containers that do not run sshd are not affected, and a pulled image is not an exposed server.
The real risk sits elsewhere: cloud images where someone later set a password, and embedded devices that, in Ars's words, "can't be easily updated, if at all." That last problem is familiar from the Videostrong TV box backdoor reported Nov. 3.
Check, patch, then restart
Work through each host in this order, as root.
- Confirm sshd is on musl without PAM and that password logins are on. Alpine's openssh-server package has no PAM; openssh-server-pam with UsePAM yes is safe.
- List the passwordless accounts with: awk -F: '$2=="*"{print $1}' /etc/shadow
- List the accounts with a real hash with: awk -F: '$2 ~ /^\$[56]\$/{print $1}' /etc/shadow
- If both print something, security firm Ethiack says it plainly: "If both commands print something and password logins are on, the host was exploitable."
Then patch. The Alpine command is apk upgrade -U -a, followed by rc-service sshd restart. The restart is not optional: "Upgrading the package does not restart a running sshd," so the old code keeps running. Fixed point releases are 3.21.10, 3.22.8, 3.23.8 and 3.24.4.
Alpine published fixed packages back to 3.16, even though 3.21 reached end of support on Nov. 1. Here is the version trap. Patched packages keep their older upstream numbers, so a scanner that only compares against 10.6p2 will flag hosts that are fine, Ethiack warns. These are the fixed packages, per Alpine.
| Alpine branch | Fixed openssh package |
|---|---|
| edge | 10.6_p2-r0 |
| 3.24 | 10.3_p1-r2 |
| 3.23 | 10.2_p1-r1 |
| 3.22 | 10.0_p1-r11 |
| 3.21 | 9.9_p2-r1 |
| 3.20 | 9.7_p1-r6 |
| 3.19 | 9.6_p1-r3 |
| 3.18 | 9.3_p2-r4 |
| 3.17 | 9.1_p1-r7 |
| 3.16 | 9.0_p1-r6 |
Source: Alpine Linux security advisory, Nov. 5.
If you cannot update yet, switch off password logins, but keep a key-based session open until a new login succeeds. As root: mkdir -p /etc/ssh/sshd_config.d, then echo 'PasswordAuthentication no' > /etc/ssh/sshd_config.d/00-no-passwords.conf, then sshd -t && rc-service sshd restart. Check with sshd -T | grep -i passwordauthentication, which should print passwordauthentication no. Alpine reads that directory from 3.19 onward; older releases ignore it, and the advisory carries a sed command for them. Miller's advice on the openssh-unix-dev list for musl without PAM: set PasswordAuthentication=no "IMMEDIATELY." The same patch-and-check problem showed up on Oct. 21 in PHP Patch Day.
Whose bug is this? The OpenSSH 10.6p2 release notes say: "We consider the root cause of this bug to be outside sshd, but it is exploitable via sshd and can be avoided there." The fix is a workaround, per The Hacker News: sshd now refuses a match when the stored field is shorter than four characters. Rich Felker, the musl developer, answered the same day: "It is my position that this is not a bug in musl just an erroneous use by the caller." He added that the mechanism "very likely will be changed in the upcoming release cycle."
My read: a convention clash with no single author, and the real repair is not shipped yet. Any other program comparing crypt() output with a stored field deserves suspicion, though nothing in the record says one exists.
The speed is part of the story. Miller wrote that OpenSSH "learned of the problem yesterday," meaning Wednesday, Nov. 4, and shipped the fix Thursday. His reason: "we have recently observed multiple cases of rapid bug rediscovery by AI agents, sometimes within hours, and so now consider long embargo periods to be a dangerous practice that primarily benefits attackers." The notes promise "more frequent releases"; 10.6p1 came 30 days earlier, on Oct. 6. Kültekin, who writes that he "had agent swarms," says an Oct. 30 security review fixed pick_salt() four lines from the bug, four days before he found it.
Last, whether anyone got in. Alpine says to look in /var/log/messages for sshd lines reading "Accepted password for" an account that has no password, such as alpine, root or any key-only user, then to review doas use, new users, files and authorized keys. "If you cannot rule out a login, treat the machine as compromised," the advisory says. Detectify (as of Thursday afternoon) and The Register (on Thursday) reported no sign of exploitation, but the details and two public reproduction labs are out there. A hit would look like Detectify's documentation example, built on a reserved test address: Nov 2 03:14:07 your-box sshd[2211]: Accepted password for alpine from 203.0.113.66 port 41822 ssh2.