On 5 November 2026 the OpenSSH project released portable 10.6p2, a workaround for an OpenSSH password bypass on Linux systems that use musl libc with PAM disabled. CERT-FR published alert CERTFR-2026-ALE-015 the same day. Özgün Kültekin of the AI security company Wakefield disclosed the flaw, and the project learned of it only a day before the release.

An attacker sends a password between 257 and 1,024 bytes long and logs in to an account that has no password. Alpine Linux OpenSSH installs are the obvious case, because Alpine builds its openssh-server package without PAM by default. Coverage mostly stops at “upgrade to 10.6p2”; that is the last of three steps. The sequence is inventory, switch passwords off, then patch.

The bug is old, not new. It dates back to 2016, and the researcher says OpenSSH 7.5p1 on musl 1.1.16 (2017) was already exploitable. What is new is the fix and the advisories; a public proof of concept and check script exist. We found no confirmed in-the-wild exploitation in the sources we read, which tells you little about next week.

How musl’s crypt() failure and sshd’s salt lookup combine

musl’s crypt() has returned the literal * on failure since 2012, and its SHA-512 crypt rejects passwords longer than 256 bytes. Since the 2016 timing mitigation for CVE-2016-6210, a non-PAM sshd takes a salt from another real account with pick_salt() and calls crypt(password, salt) even for accounts that cannot log in with a password.

Send a password in the working range and crypt() fails with *. That equals the * stored in /etc/shadow for a passwordless account, so sshd sees a match. The overlap of those two behaviours creates the hole; neither one is a bug on its own.

CERT-FR words the length as “strictly more than 256 and less than 1024”, while other sources say 257 to 1,024 bytes. The difference at the upper edge does not change the audit below. Advisories also differ on whether the attacker sends one long password or two; again the audit is the same either way.

The reported conditions are no PAM, password logins enabled, and an account whose shadow field is exactly *. Secondary sources add that another account with a $5$ or $6$ hash must exist. We could not confirm what happens without one, so do not treat its absence as protection.

Not affected: glibc systems, UsePAM yes, Dropbear, OpenBSD and non-Linux systems. An Alpine package built with PAM is still exposed if sshd runs with UsePAM no.

Why key-only accounts are the targets

The accounts with * in the password field are typically key-only ones. The researcher lists root, key-only users and LDAP users, plus the default alpine user on Alpine’s official cloud images 3.18.11 to 3.24.3, which has no password. One write-up says that user has passwordless doas, which makes the bypass effectively root.

A key-only account is only key-only if sshd refuses passwords. Until PasswordAuthentication is off, “no password set” means “any password that makes crypt() fail”.

OpenSSH’s default for PasswordAuthentication is yes. If nobody set it to no, nothing stops a password attempt against those * accounts.

Step 1: inventory hosts, then images

Start with every machine that runs sshd, then narrow to musl, then to password logins. On each host, as root:

ldd --version 2>&1 | head -n1
sshd -T | grep -i -E '^(usepam|passwordauthentication)'
awk -F : '$2 == "*" {print $1}' /etc/shadow

The ldd and sshd -T lines are standard tooling that we have not checked against the advisory; the awk line comes from CERT-FR. The first shows which libc the host runs; on musl it names musl. The second shows the effective sshd settings. The third lists the accounts an attacker would target. None of them proves whether your sshd was built with PAM: for that test, use the researcher’s check script and Alpine’s advisory, and do not infer “no PAM” from a missing line of output.

Then check whether anyone already used the hole. CERT-FR’s compromise check combines the account list with the log:

awk -F : '$2 == "*" {print $1}' /etc/shadow | xargs -r -I{} grep "Accepted password for {}" /var/log/messages

The path /var/log/messages is Alpine’s syslog default. On other setups, point it at your log file or query journald. An accepted password login for a key-only account is a finding, whatever else you conclude.

For a container image audit, first check whether the image contains an SSH server at all. You can do that without treating the image as a host: run it once and list the installed packages, for example docker run --rm --entrypoint apk your-image info -v | grep openssh (standard tooling, not confirmed against the advisory). Then compare versions against the fixed packages: edge 10.6_p2-r0, 3.24 10.3_p1-r2, 3.23 10.2_p1-r1, 3.22 10.0_p1-r11 and 3.21 9.9_p2-r1. Older branches back to 3.16 carry backports rather than the 10.6p2 version number, and we did not retrieve those versions, so take them from Alpine’s advisory. Run the researcher’s check script for the PAM question.

Do not stop at images you built. Buildroot, Yocto and OpenWrt devices can use musl, and the researcher also lists postmarketOS, Void-musl and Chimera. Whether each is exposed depends on how its OpenSSH was built.

Where your VPS, VDS and Bare Metal fleet fits

On unmanaged VPS and VDS the guest operating system and sshd are yours to check, so the commands above are yours to run. The same goes for Bare Metal unless you took the managed option, where we patch the operating system; ask us to confirm the sshd version rather than assuming it. The same commands apply wherever you run Linux with OpenSSH on it.

Reachability is a second layer. If your administrators reach hosts over Private Link, you can restrict who can reach sshd at all; that shrinks the audience, it does not fix sshd.

Step 2: SSH key-only hardening in sshd_config

CERT-FR’s official mitigation is to disable password authentication, or the service if you cannot patch. Damien Miller of OpenSSH says the same: set PasswordAuthentication no and restart sshd. This is the official mitigation and needs no new package. It takes effect only once sshd is restarted, or the container is recreated from an image that carries the setting.

  1. Confirm every administrator has a working key and a second session open.
  2. Set PasswordAuthentication no in /etc/ssh/sshd_config or a drop-in it includes, then restart sshd.
  3. Re-run sshd -T | grep -i passwordauthentication and confirm it reads no. Also read your Match blocks by hand.
  4. Bake the setting into the image or config management so the next rebuild does not revert it.

Step 3: patch, and what 10.6p2 changes

10.6p2 makes sshd refuse a match when the stored password field is shorter than four characters. OpenSSH itself calls this a workaround and says the root cause lies outside sshd. musl’s maintainer, Rich Felker, says it is not a musl libc vulnerability.

That argument decides your plan: the fix is a guard in one daemon, not a change in the library. Upgrade sshd once passwords are off, and put the check for * accounts with password logins into your image pipeline so a rebuilt image cannot bring the exposure back quietly.

Sources