On 5 November 2026 the Alpine Linux team and the OpenSSH project published a fix for a password authentication bypass in sshd on Alpine. On an affected server, an attacker can log in to an account that has no password at all, such as a user who normally signs in only with an SSH key, simply by sending a password longer than 256 bytes. The researcher who reported it, Özgün Kültekin of Wakefield, nicknamed it sshole, and it has been reported under CVE-2026-123158. The fix is in OpenSSH 10.6p2 and in updated openssh packages for every Alpine release from 3.16 to 3.24. No attacks had been confirmed in the first reports, but the technique is trivial and now public, so scanning is expected soon.
How a Long Password Gets Through
The bug sits between two components that each behave reasonably on their own. Alpine ships sshd without PAM by default, so sshd checks a password itself: it runs the typed password through the C library function crypt() using the salt from /etc/shadow, then compares the result with the stored hash.
Accounts that should never log in with a password have an asterisk in the password field of /etc/shadow instead of a hash. On Alpine this is the case for root in base images since 3.16, for users who sign in only with keys, and for some directory service accounts. To avoid revealing which accounts exist through response times, sshd does not stop early for these accounts. It borrows a real salt from another account and runs crypt() anyway, a behaviour that goes back to a change made in 2016.
The C library on Alpine is musl, and musl refuses to hash keys longer than 256 bytes. When that happens, its crypt() returns an asterisk to signal an error. sshd then compares that asterisk with the asterisk stored for the passwordless account, the two strings are equal, and the login is accepted. There is no weak cryptography and no memory corruption involved, only two meanings of the same character. OpenSSH developer Damien Miller said the project considers the root cause to be outside OpenSSH itself. The fix in sshd rejects stored values that are too short to be a valid hash, so an error result can no longer match.
Is Your Server Affected
A system is exploitable only when all of the following are true. Many Alpine machines meet every one of them with default settings.
- It runs OpenSSH sshd from the openssh-server package, which is built without PAM, or from openssh-server-pam with UsePAM set to no.
- PasswordAuthentication is enabled, which is the default.
- At least one account with an asterisk in its password field can log in over SSH. Root has an asterisk since Alpine 3.16, but the default PermitRootLogin prohibit-password blocks password logins for root. The more realistic targets are key-only users, directory service users, and the alpine user in tiny-cloud cloud images.
- At least one other local account has a real password hash, starting with $5$ or $6$, which sshd uses as the borrowed salt.
The tiny-cloud case is the most serious. Alpine cloud images built with tiny-cloud from 3.18.11 to 3.24.3 include an alpine user with an asterisk as its password and passwordless doas. As soon as any account on that machine gets a real password, an attacker can log in as alpine and become root in one more command.
Systems that are not affected: Alpine containers that do not run sshd, which covers most images such as node:alpine or nginx:alpine; any system with PasswordAuthentication set to no; the PAM build with UsePAM yes; locked accounts that have an exclamation mark rather than an asterisk; and distributions that use glibc, such as Ubuntu, Debian, and Red Hat Enterprise Linux. Alpine maintainers have also said Dropbear is not affected. Other musl-based systems that run OpenSSH without PAM, for example some Buildroot or Yocto builds for embedded devices, have the same weakness and need the OpenSSH 10.6p2 fix.
Checking in a Few Commands
Run these as root on each Alpine machine that has sshd. They only read the current state and change nothing.
- Alpine release and installed packages: cat /etc/alpine-release and apk list -I "openssh*". Compare the openssh version with the table in the next section.
- Effective sshd settings: sshd -T | grep -Ei "^(usepam|passwordauthentication|permitrootlogin) ". This shows the values sshd actually uses after all configuration files are combined, which is more reliable than reading sshd_config by eye.
- Accounts without a password: awk -F: '$2=="*" {print $1}' /etc/shadow lists the accounts that could be opened with this bug.
- Accounts with a real hash: grep -cE ':\$[56]\$' /etc/shadow counts them. If the result is zero there is no salt to borrow and the bug cannot be triggered, but that is a fragile protection, since it disappears as soon as anyone sets a password.
Fixed Versions
| 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 |
Alpine also built fixes for releases that are no longer supported, back to 3.16, which it rarely does. Take that as a sign of how serious the issue is, not as a reason to stay on an old release. The new point releases 3.21.10, 3.22.8, 3.23.8, and 3.24.4 already contain the fixed package, so images and installs built from them are safe.
How to Update
- 1Update the packages with apk upgrade -U -a, then confirm the openssh version with apk list -I "openssh*".
- 2Restart sshd with rc-service sshd restart. This step is required: the running daemon keeps the old code until it is restarted, and an upgrade alone leaves the server exploitable. Existing SSH sessions stay open during the restart.
- 3For containers that run sshd, such as SFTP or jump host containers, rebuild the image from the updated base, make sure the build installs the fixed openssh package, and recreate the container. Patching inside a running container is lost the next time it is recreated.
- 4For cloud instances started from older tiny-cloud images, update them the same way, and update any custom images or templates so new instances do not start with the old package.
- 5Check every machine again with sshd -T and apk list -I, rather than assuming the update reached all of them.
If You Cannot Update Today
Turning off password authentication removes the problem completely, and on a server that is reachable from the internet it is the right setting anyway. First confirm that you can log in with an SSH key, and keep one session open while you make the change so a mistake does not lock you out.
- 1On Alpine 3.19 and later, create a file in /etc/ssh/sshd_config.d/ with a name that sorts early, for example 00-no-password.conf, containing the line PasswordAuthentication no. sshd uses the first value it reads, so an early file name makes sure this setting wins. On 3.16 to 3.18, change the line in /etc/ssh/sshd_config directly.
- 2Validate the configuration with sshd -t. If it prints nothing, the syntax is correct.
- 3Restart with rc-service sshd restart, then confirm with sshd -T | grep -i passwordauthentication that the result is no.
- 4From a new terminal, log in with your key to make sure access still works before closing the old session.
If some users genuinely need password logins, limit who can reach port 22 instead, for example through a firewall that only allows the office or VPN addresses, until the update is done.
Checking Whether Someone Already Got In
The exploit does not leave a distinctive log entry. A login through this bug looks like a normal successful password login. The useful check is therefore whether a password login succeeded for an account that has no password. Search /var/log/messages for Accepted password for, and compare the user names with the list of asterisk accounts from the check above. Also review doas usage, recently created users, changes to authorized_keys files, and recently modified files in system directories. Containers often do not keep logs once they are recreated, which makes this harder. If you cannot rule out that someone logged in, treat the machine as compromised and rebuild it rather than trying to clean it.
What This Bug Shows
Most Alpine machines that were exploitable had two things in common: password authentication was left at its default, and the SSH port was open to the whole internet. Either one done differently would have kept them safe. For servers that face the internet, sign in with keys or SSH certificates only, put SSH behind a VPN or a bastion host where possible, and keep a list of which machines run sshd at all, including small Alpine VMs and containers that are easy to forget. Also make restarting services part of every security update, because on Alpine nothing reminds you that a daemon is still running the old code. If you would like help checking or hardening your servers, our managed service team can take it on.
Key takeaways
- On Alpine, sshd without PAM accepts any password longer than 256 bytes for accounts that have an asterisk instead of a password, because musl crypt() returns an asterisk on error.
- Affected setups run sshd with PasswordAuthentication enabled, have at least one passwordless account that can log in, and at least one account with a real hash. Containers without sshd and glibc distributions are not affected.
- Install the fixed openssh package for your branch, for example 10.3_p1-r2 on 3.24, and restart sshd. The upgrade alone does not protect a running server.
- If you cannot update yet, set PasswordAuthentication no after confirming key login works, or restrict who can reach port 22.
- Look for password logins to passwordless accounts in /var/log/messages, and rebuild any machine where a break-in cannot be ruled out.


