OpenSSH CVE-2026-123158 "SSHole": A Long Password Logs In on Alpine. Patch by Nov 12
A password-authentication bypass in sshd built without PAM lets a single long password log in to accounts that have no password at all. Alpine is the main target, CISA lists it as exploited, and the federal deadline is November 12. Checks, fixed packages and the one-line stopgap.
Key takeaways
- CVE-2026-123158, nicknamed SSHole, is a password-authentication bypass in OpenSSH's sshd when it runs without PAM on musl-based Linux, which in practice means Alpine.
- CISA added it to the KEV catalog on November 9, 2026, with a November 12 deadline.
- Upgrade to OpenSSH 10.6p2 or your branch's fixed Alpine package and restart sshd, or set PasswordAuthentication no.
On this page
Upgrade openssh on every Alpine host, VM image and container that runs sshd, then restart the daemon. CVE-2026-123158 lets one connection with an overlong password log in to accounts that have no password set, such as key-only users. CISA lists it as exploited, and the federal deadline is November 12. If you cannot patch today, turn off password authentication.
Verified against
OpenSSH 10.6p2 and the fixed Alpine packages for 3.16 through 3.24 and edge, against the OpenSSH 10.6p2 release notes, the Alpine Linux security post of November 5, 2026, openssh-portable commit 4353fdc and the CISA KEV catalog feed. Checked November 2026.
What happened, in dates
- November 5, 2026: OpenSSH 10.6p2 ships with a fix for "password authentication bypass that is exploitable through sshd(8) that affects some Linux systems when built and run with PAM support disabled." The same day, Alpine publishes its advisory and fixed packages for every branch from 3.16 to edge. The bug was reported by Özgün Kültekin of Wakefield.
- November 9: CISA adds CVE-2026-123158 to the Known Exploited Vulnerabilities catalog. The entry asks for forensic triage, lists ransomware use as unknown, and sets a remediation due date of November 12, 2026.
OpenSSH says it considers the root cause to be outside sshd, but closes the hole there because sshd is where it can be reached.
How a long password becomes a login
Without PAM, sshd checks a password itself. It hashes your attempt with crypt() using the salt from the account's shadow entry, then compares the result with the stored value. Alpine's advisory spells out how that goes wrong on musl:
- An account with no password has
*in its shadow password field. Stock Alpine shipsroot:*(the defaultPermitRootLogin prohibit-passwordkeeps root out), and key-only users, directory-service users without a shadow entry and thealpineuser in tiny-cloud images are in the same position. *is too short to hold a salt, so sshd borrows a salt from another account on the box that has a real$5$or$6$hash.- musl's
crypt()returns*as its error value when the key is longer than 256 bytes. - A password of 257 to 1,024 bytes therefore "hashes" to
*, which matches the stored*, and sshd lets the attacker in.
The upstream commit adds a minimum hash-length check before the comparison, so a stored value as short as * can no longer match. Glibc systems and anything using PAM do not take this path.
Am I affected?
You need all four of these at once: sshd without PAM (the openssh-server package, or openssh-server-pam with UsePAM no), password authentication on (the OpenSSH default), at least one account whose password field is *, and at least one account with a $5$ or $6$ hash.
# 1. Which sshd build is installed? openssh-server is the non-PAM build.
apk info -v 2>/dev/null | grep '^openssh-server'
# 2. What the running config actually allows (needs root)
sshd -T | grep -E '^(usepam|passwordauthentication) '
# 3. Accounts with no password, and accounts with real hashes
awk -F: '$2 == "*" {print "no-password:", $1}' /etc/shadow
awk -F: '$2 ~ /^\$[56]\$/ {print "hashed:", $1}' /etc/shadow
# 4. Kubernetes: which pods are running an sshd process right now?
kubectl get pods -A -o jsonpath='{range .items[*]}{.metadata.namespace}{" "}{.metadata.name}{"\n"}{end}' \
| while read -r ns pod; do
kubectl exec -n "$ns" "$pod" -- sh -c 'pgrep -x sshd >/dev/null && cat /etc/alpine-release' 2>/dev/null \
| sed "s|^|$ns/$pod alpine |"
done
# 5. An image you build or pull: does it ship the non-PAM sshd?
docker run --rm --entrypoint sh <image> -c 'cat /etc/alpine-release; apk info -e openssh-server'
You are exposed if check 1 shows openssh-server (the non-PAM build prints no usepam line in check 2) or check 2 shows usepam no, check 2 shows passwordauthentication yes, and check 3 prints at least one line of each kind. Check 4 is slow on big clusters, so run it per namespace; it only inspects each pod's default container, and only reports it if that container has a shell, pgrep and Alpine.
Fixed Alpine packages, as of November 11, 2026
| Alpine branch | Fixed openssh package | Fixed point release |
|---|---|---|
| edge | 10.6_p2-r0 | n/a |
| 3.24 | 10.3_p1-r2 | 3.24.4 |
| 3.23 | 10.2_p1-r1 | 3.23.8 |
| 3.22 | 10.0_p1-r11 | 3.22.8 |
| 3.21 | 9.9_p2-r1 | 3.21.10 (support ended Nov 1) |
| 3.20 | 9.7_p1-r6 | none, unsupported |
| 3.19 | 9.6_p1-r3 | none, unsupported |
| 3.18 | 9.3_p2-r4 | none, unsupported |
| 3.17 | 9.1_p1-r7 | none, unsupported |
| 3.16 | 9.0_p1-r6 | none, unsupported |
Upstream, the fix is OpenSSH 10.6p2. Tiny-cloud VM images (qcow2, VHD, AMI) from 3.18.11 through 3.24.3 are safe at first boot but become exploitable once any account gets a $6$ password, and their alpine user has passwordless doas. That makes a hit on that user a root compromise.
What to do now
Patch and restart. Upgrading the package does not replace the daemon that is already running:
apk upgrade -U -a
rc-service sshd restart
apk info -v openssh-server # compare with the table above
For containers, rebuild on a fixed base (alpine:3.24.4, 3.23.8, 3.22.8 or 3.21.10) and redeploy. A restart alone pulls nothing new.
Stopgap: turn off password logins. Alpine's default sshd_config reads drop-in files from 3.19 onward; older releases ignore them, and Match blocks in sshd_config need editing separately:
mkdir -p /etc/ssh/sshd_config.d
echo 'PasswordAuthentication no' > /etc/ssh/sshd_config.d/00-no-passwords.conf
sshd -T | grep '^passwordauthentication ' # expect: passwordauthentication no
sshd -t && rc-service sshd reload
Confirm key-based login works in a second session before you close the one you are in. Our SSH hardening guide covers moving the rest of the fleet to keys and certificates.
Where this breaks
The stopgap does nothing if another config line later turns password authentication back on, so trust the sshd -T output, not the file you edited. Patching does not tell you whether someone already got in. Alpine's advice is to search /var/log/messages for Accepted password for on accounts that have no password, then review doas use, new accounts, new files and authorized_keys. If you cannot rule out a login, treat the machine as compromised and rebuild it. Finally, containers that run sshd at all are the bigger problem: an image that needs a debug shell is better served by kubectl exec or an ephemeral debug container, and a distroless base removes the option entirely.
Questions people ask
Is Ubuntu or Debian affected by CVE-2026-123158?
Not through this path. The bypass depends on musl's crypt() returning * for overlong keys, and on sshd running without PAM. Ubuntu and Debian use glibc, build sshd with PAM and ship UsePAM yes. Take the update when your distribution ships it, but the emergency is Alpine and other musl systems with PAM off.
Does disabling root login stop SSHole?
It protects root only, and the default PermitRootLogin prohibit-password already does that. Any other account with * in its password field is still a target: key-only users, directory-service users and the alpine user in tiny-cloud images, which can reach root through doas. Setting PasswordAuthentication no closes the bypass for every account, and patching removes it. Check /etc/shadow for * entries to see which users are exposed.
Do I need to restart sshd after apk upgrade?
Yes. apk upgrade replaces the binary on disk, but the listening daemon keeps running the old code until it restarts. Run rc-service sshd restart, or reboot. In Kubernetes, a pod keeps its image until it is recreated, so rebuild the image on a fixed Alpine release and roll the deployment.
The call we'd make
Treat any Alpine host or image that runs sshd as exposed until apk info -v openssh-server shows the fixed package and the daemon has restarted, and push PasswordAuthentication no everywhere today, since it costs nothing on a key-only fleet. The caveat: CISA has evidence of exploitation, so on hosts that were reachable with passwords on, patching is the start of the work, not the end. Check the logs.
Sources
Cite this article
Kiril Urbonas (2026). OpenSSH CVE-2026-123158 "SSHole": A Long Password Logs In on Alpine. Patch by Nov 12. DevOpsNess. https://www.devopsness.com/blog/openssh-cve-2026-123158-sshole-alpine-password-bypass
[OpenSSH CVE-2026-123158 "SSHole": A Long Password Logs In on Alpine. Patch by Nov 12](https://www.devopsness.com/blog/openssh-cve-2026-123158-sshole-alpine-password-bypass) (Kiril Urbonas, DevOpsNess, 2026-11-11)
More from Linux
Explore more articles in this category
CVE-2026-98432: The CVSS 9.8 Linux TCP Bug Now Has an Exploit. Patched Node Images
A use-after-free in the IPv4 TCP handshake, present since Linux 4.4, now has a working exploit against MPTCP listeners, and every Go 1.24+ server is one by default. Which kernels are fixed and how to roll them through EKS, GKE and AKS.
CERN Left Red Hat for Debian: The CPU Baseline Lesson
CERN is moving accelerator control computers to Debian because RHEL raised its minimum CPU level. Check your own fleet's x86-64-vN support before the next OS upgrade does it for you.
ext4 vs XFS vs Btrfs: Choosing a Filesystem for a Server
The default filesystem your distro picks is not always the right one for your workload. Here is what actually differs and when each one wins.
You might have missed
Evergreen posts worth revisiting.