What Alpine's *sshole SSH login bypass means for you
A 257-byte password can open key-only accounts on some Alpine Linux machines. Here is why it works, who is exposed, and what to run now.
According to the Alpine Linux security advisory, an attacker who can reach your SSH port can log into some Alpine machines without knowing any password, and it takes one connection. The attack rests on a single collision. musl’s crypt() function returns the string * as an error when a password is longer than 256 bytes. * is also exactly what the password field holds for accounts that have no password. So if an attacker sends an over-long password to a passwordless account, the error looks like a correct answer.
The background you need
How Linux stores passwords. Linux does not store your password. It stores a hash of it in /etc/shadow. A typical entry looks like $6$abc$k2P9…. According to the discoverer’s write-up at sshole, $6$ means SHA-512, abc is the salt, and the rest is the hash. A salt is a random prefix mixed in before hashing, so two users with the same password end up with different hashes. $5$ is the SHA-256 version.
What crypt() does. crypt() is the C library function that turns a password attempt plus a salt into a hash. To check a login, a program hashes what you typed with the stored salt. Then it compares the result to the stored field. If the two strings are the same, you’re in.
What * means. An account whose password field is just * has no password. * is not a valid hash, so no password should ever produce it. This is the standard way to make an account key-only. The account can log in with an SSH key but never with a password. The sshole site traces the convention back to early Unix.
musl versus glibc. Almost every Linux program relies on a C library, called libc. Most distributions use glibc. Alpine uses musl, a smaller alternative. The two implement the same functions but differ in details. One of those details is what crypt() returns when it fails.
PAM. Pluggable Authentication Modules (PAM) is a framework that handles logins on behalf of programs like sshd. The advisory describes what happens when sshd is built without PAM. In that case, sshd hashes the attempt itself and compares the strings directly. The sshole site says most distributions route sshd through PAM, and PAM never calls crypt() for a * account.
Why sshd borrows salts. A * field contains no salt. The sshole site explains the history. An old fix for a timing leak (CVE-2016-6210) made sshd hash a password even when there is no real hash to check. That way a failed login takes the same time either way, and attackers can’t time responses to learn which usernames exist. To do that hashing, sshd borrows the salt from another account on the machine. The Alpine advisory confirms this borrowing for any account whose stored field is too short to contain a salt.
Why musl returns *. The sshole site says musl chose to return a short failure string from crypt() instead of NULL, an empty pointer. Many programs never check for NULL and crash when they get one. The failure string was meant to never match a real password. Separately, musl caps SHA-512 crypt input at 256 bytes. Long inputs make the hashing slow, and an attacker could use that to tie up a server.
Here is an analogy. Picture a vault door with a red lamp that means closed for good. A guard lets you in only if your badge scan lights a lamp that matches the one on the door. No badge produces that lamp, so the door stays shut. But the scanner’s error lamp happens to be the same red. Jam the scanner and the lamps match, so the guard waves you in. The analogy breaks in one place. Nothing is physically jammed here. The software is simply comparing two strings, and the jam is just a password longer than 256 bytes.
What actually changed
The bug is not new. The sshole site says it has existed since 2016, and Ars Technica calls it decade-old. What is new is that it has now been disclosed and fixed.
According to the advisory, an attacker needs three things:
- a reachable sshd that accepts password logins
- the name of an account whose password field is
* - at least one other account with a
$5$or$6$hash, which supplies the borrowed salt
The attacker then sends a password between 257 and 1024 bytes long. The advisory says one user with a password is enough to make every passwordless account reachable. Ars reports that security firm Checkpoint tested this. Checkpoint found that the account supplying the hash must be active, not merely contain a hash.
OpenSSH released version 10.6p2, which avoids the problem in sshd. Alpine shipped patched packages and point releases 3.21.10, 3.22.8, 3.23.8 and 3.24.4. The advisory says every release it checked is affected: 3.21 through 3.24, edge, and the older 3.16 to 3.20. It has published fixed packages for each release back to 3.16. No CVE identifier had been assigned when the advisory and the Ars article were published.
The projects disagree about whose bug this is. According to Ars, OpenSSH said it considers the root cause to be outside sshd, though the bug is exploitable through sshd and can be avoided there. musl developer Rich Felker said it is not a bug in musl but an erroneous use by the caller. He added that musl plans to change the mechanism in an upcoming release.
What it means for you
The 256-byte error colliding with the * field is the detail that decides whether you are at risk. Check your machine against those conditions:
- Does it use musl?
- Does sshd check passwords itself, without PAM?
- Is password authentication on?
- Is there at least one
*account? - Is there at least one account with a
$5$or$6$hash?
If any answer is no, the collision never happens.
Here is what follows from that:
- Cloud images. The advisory says official tiny-cloud images (qcow2, VHD and AMI) from 3.18.11 through 3.24.3 ship an
alpineuser with a*password field and passwordlessdoas. They are safe on first boot. They become exploitable once any$6$hash exists on the machine, for example after an admin sets a console password. An attacker then gets a shell asalpineand can usedoasto become root. Images built from earlier point releases do not include the fix, so running instances need patching. - Root. The sshole site lists root among the accounts that will take a long password. Ars reports that Checkpoint found root safe under the default
PermitRootLogin prohibit-passwordsetting. Accounts withdoasorsudorights can still be used to reach root. Check your own setting. - Other systems. Ars says other platforms with the same configuration may be affected. The discoverer names OpenWRT, buildroot and yocto. Ars notes that OpenWRT uses Dropbear rather than OpenSSH by default, and that buildroot and yocto are not confirmed. The sshole site says glibc distributions, PAM setups, Dropbear and OpenBSD are fine.
- Scale. Ars cites security firm Detectify, which says the search engine Shodan lists around 22 million systems with SSH open on port 22. Only a fraction meet the conditions. Ars notes that testing each system is quick, so finding vulnerable ones takes little effort.
The advisory gives these steps:
- Run
apk upgrade -U -a, thenrc-service sshd restart. - If you can’t update yet, set
PasswordAuthentication noand restart sshd. Alpine says either step closes the hole. Ars recommends installing both the Alpine and OpenSSH patches on affected systems. - Search
/var/log/messagesforAccepted passwordlines for accounts that have no password, such asalpine,rootor any key-only user. - Review recent
doasuse, newly created users, new files and authorized keys on exposed machines.
If you can’t rule out a login, the advisory says to treat the machine as compromised.
What we don’t know yet
- Which other systems are affected. Ars says it is not yet known which other packages are vulnerable.
- Whether anyone used it before disclosure. The sshole site says that as far as anyone knows, nobody noticed. It also guesses that someone may have been let in by accident after pasting long text into a password prompt. That is speculation, not evidence.
- When musl will change
crypt(). Felker said changes are planned for an upcoming release. The reports give no date. - Whether a CVE will be assigned. None existed when the reports were published.
- Whether embedded devices will be fixed. Ars notes that many routers, TVs and industrial controllers running Alpine can’t be easily updated, if at all.
FAQ
I run Ubuntu or Debian. Am I affected?
Does the attacker need to know any password?
Is turning off password logins enough?
Related reading
2026-10-30
What Mistral Large 4's open weights mean for coders
Mistral released the weights of its 1-trillion-parameter model. Its real selling point is matching rivals while using far fewer tokens per task.
2026-10-21
What the critical PHP RCE patch means for you
PHP shipped an emergency fix for two unauthenticated remote code execution bugs. Here is what the CVEs are, why there is no mitigation, and what to do.
2026-10-19
What Let's Encrypt's two new validation points mean
Let's Encrypt will check your domain from six remote networks instead of four. Here's why the rules demand it and who should test before November 10.
2026-10-17
What the solved NIST P-256 seed mystery means
The unexplained seeds behind P-256 and its sibling curves turn out to be clock-seeded lrand48 output. Here is why that matters and what is still open.
2026-10-14
What the 11-year-old Rust borrow checker bug means
A newly reported Rust soundness hole lets safe code read freed memory. Here is what lifetimes, variance and Drop have to do with it, and who should care.
Get the best tools, weekly
One email every Friday. No spam, unsubscribe anytime.