sshole (CVE-2026-123158): OpenSSH Alpine Linux Password Bypass
OpenSSH 10.6p2 patches sshole (CVE-2026-123158, CVSS 8.1), a password bypass on Alpine Linux and musl systems without PAM. Check affected branches and fixes.


On this page
On this page8 sections
OpenSSH has shipped an emergency release, version 10.6p2, to stop a critical password authentication bypass tracked as CVE-2026-123158 and nicknamed “sshole” (*sshole). Disclosed on November 5, 2026, by researcher Özgün Kültekin of Wakefield, the vulnerability allows an unauthenticated remote attacker to log in to passwordless accounts including SSH key-only users and default cloud accounts by sending any password between 257 and 1,024 bytes in a single connection.
The CVE-2026-123158 flaw affects Linux systems running the OpenSSH daemon (sshd) linked against the musl C standard library (musl libc) with Pluggable Authentication Modules (PAM) disabled. Because that exact combination is the default build for the openssh-server package on Alpine Linux, Alpine maintainers released backported patches on November 5, 2026, covering every release branch from Alpine 3.16 through 3.24 and edge.
Following recent runtime advisories such as PHP2Shell (CVE-2026-109618) and the Node.js Brotli RCE (CVE-2026-111497), sshole demonstrates how subtle edge cases between a daemon and its underlying C library can silently subvert authentication for a decade. This guide breaks down the exact four conditions required for exploitation, how musl and OpenSSH collide on the "*" string, which Alpine packages fix the flaw, and how to patch and hunt for unauthorized logins immediately.
What to Remember
- The Flaw (CVE-2026-123158): Rated CVSS 3.1 8.1 (High) by MITRE and Critical by the OpenSSH project,
sshole(CWE-394) lets a remote attacker authenticate to accounts whose/etc/shadowpassword field is*by submitting any 257-to-1,024-character password. - Narrow Scope (musl + No PAM): The bypass affects OpenSSH before 10.6p2 on Linux systems built with
musl libcand running without PAM (most notably Alpine Linux, plus custom OpenWrt, Buildroot, or Yocto builds usingopenssh-server). Standardglibcdistributions (Ubuntu, Debian, RHEL, Fedora), PAM-enabled setups, OpenBSD, and Dropbear SSH are not affected. - Four Mandatory Conditions: A server is vulnerable only when it runs
sshdonmuslwithout PAM, keepsPasswordAuthentication yes(the default), has at least one account with*in/etc/shadow, and has at least one other local account with a$5$(SHA-256) or$6$(SHA-512) password hash. - Indirect Root Risk on Cloud Images: While OpenSSH’s default
PermitRootLogin prohibit-passwordblocks direct root password logins, official Alpinetiny-cloudimages (3.18.11 through 3.24.3) grant the passwordlessalpineaccount (alpine:*) unrestricted root escalation viadoas. - Restart Required After Patching: Running
apk upgrade -U -ainstalls the fixed package on disk, but the vulnerablesshdbinary remains active in memory until you runrc-service sshd restart. - Immediate Workaround: If you cannot upgrade right away, setting
PasswordAuthentication noinsshd_configand restartingsshdcompletely blocks the attack vector.
1. What Is the sshole Vulnerability (CVE-2026-123158)?
In Unix and Linux environments, placing a single asterisk (*) in the password hash field of /etc/shadow designates an account that cannot authenticate with a password. Administrators and image builders routinely use * for SSH key-only deploy accounts, service accounts, directory-backed users (musl-nscd), and the root user on Alpine Linux. Because no valid cryptographic hash outputs a single character, a * entry is supposed to reject every possible password input while still allowing SSH public-key logins when PAM is absent.
Under CVE-2026-123158, that security assumption fails on musl-based OpenSSH servers. When an attacker sends a password exceeding 256 bytes, musl’s crypt() function rejects the input and returns the literal string "*" to indicate an error. Because sshd compares the output of crypt() directly against the stored /etc/shadow field ("*"), the comparison succeeds and logs the attacker in on the first attempt.
| Attribute | Technical Detail |
|---|---|
| CVE Identifier | CVE-2026-123158 (nicknamed sshole / *sshole) |
| Severity Rating | CVSS v3.1: 8.1 (High) (MITRE CNA) / Critical (OpenSSH Project) |
| Weakness Classification | CWE-394: Unexpected Status Code or Return Value |
| Affected Software | Portable OpenSSH versions prior to 10.6p2 on Linux with musl libc and no PAM |
| First Fixed Version | OpenSSH 10.6p2 (released November 5, 2026) and backported Alpine packages |
| Exploit Payload | Any arbitrary password string between 257 and 1,024 bytes |
| Discovery & Reporting | Özgün Kültekin (Wakefield), disclosed November 5, 2026 |
| In-the-Wild Exploitation | Public PoCs available; no confirmed in-the-wild exploitation as of November 6 |
The 4 Conditions Required for Exploitation
According to the official Alpine Linux security advisory, all four of the following prerequisites must be present on a host for CVE-2026-123158 to be exploitable:
sshdRuns onmuslWithout PAM: The server runs the standard Alpineopenssh-serverpackage (which is compiled without PAM support) or runsopenssh-server-pamwithUsePAM no.- Password Logins Are Enabled:
PasswordAuthenticationis set toyesin/etc/ssh/sshd_config(which is the default setting in upstream OpenSSH and Alpine’s package). - A Passwordless (
*) Target Account Exists: At least one valid account has*as its password field in/etc/shadow(or comes from a directory service viamusl-nscdwithout a shadow entry). - A Real SHA-256 or SHA-512 Hash Exists Elsewhere on the Host: At least one other local account on the machine has a password hash starting with
$5$(SHA-256) or$6$(SHA-512). One user with a real password is sufficient to expose every*account on the system.
2. How the Overlong Password Bypass Works Under the Hood
The sshole authentication bypass is not a memory-corruption bug or a cryptographic flaw. Instead, CVE-2026-123158 is an architectural collision between three separate engineering decisions made between 2012 and 2022 across musl libc, Portable OpenSSH, and Alpine Linux.
┌──────────────────────────────────────────────────────────────────────────────┐
│ CVE-2026-123158 (*sshole) Execution Flow │
├──────────────────────────────────────────────────────────────────────────────┤
│ │
│ 1. Attacker connects to sshd as passwordless user "alice" (/etc/shadow: *) │
│ and submits a 300-byte password ("AAA...AAA"). │
│ │ │
│ ▼ │
│ 2. sshd (built without PAM) calls sys_auth_passwd() -> xcrypt(pw, salt). │
│ Because alice's stored hash "*" is < 2 chars, it contains no valid salt. │
│ │ │
│ ▼ │
│ 3. To prevent timing user enumeration (CVE-2016-6210), sshd calls │
│ pick_salt() and borrows a real "$6$..." salt from local user "bob". │
│ │ │
│ ▼ │
│ 4. sshd calls musl's crypt("AAA...AAA", "$6$bob_salt$"). │
│ musl SHA-512 crypt enforces KEY_MAX = 256 bytes for DoS protection. │
│ │ │
│ ▼ │
│ 5. Password length (300) > 256 bytes -> musl crypt() fails and returns │
│ the literal error token "*" instead of NULL. │
│ │ │
│ ▼ │
│ 6. sshd compares strcmp(encrypted_password, pw_password): │
│ strcmp("*", "*") == 0 ──► AUTHENTICATION ACCEPTED │
│ │
└──────────────────────────────────────────────────────────────────────────────┘Three Design Decisions Across a Decade (2012–2022)
Each component behaved according to its own local rationale, but their combination created a deterministic authentication bypass:
- August 2012 (
muslReturns"*"Instead ofNULLon Error): POSIX specifies thatcrypt()should return aNULLpointer when hashing fails. Because many legacy C programs passed the return value ofcrypt()directly intostrcmp()without checking forNULLcausing segmentation faultsmuslcommitb3c4cc12changedcrypt()to return a static “unmatchable” string ("*", or"x"if the salt itself started with"*") on failure. Twenty days later,muslcommit88bf5a8aadded SHA-256 ($5$) and SHA-512 ($6$) support with a hard 256-byte password limit (#define KEY_MAX 256) to prevent CPU denial-of-service (DoS) attacks. Any password over 256 bytes with a$5$or$6$salt therefore causesmusl’scrypt()to return"*". - July 2016 (OpenSSH Borrows Salts via
pick_salt()): To patchCVE-2016-6210(a timing side-channel that let attackers enumerate valid usernames by measuring whethersshdspent CPU cycles hashing a password), OpenSSH 7.3 (commit 9286875a7) introducedpick_salt()inopenbsd-compat/xcrypt.c. Whenever a target account’s password field is too short to contain a valid 2-character salt such as"*"sshdscans the local password database and borrows a$5$or$6$salt from another user on the host socrypt()still performs a full SHA-256 or SHA-512 computation. Additionally, OpenSSH 7.3 capped accepted passwords atMAX_PASSWORD_LEN(1,024 bytes), establishing the 257-to-1,024-byte exploit window. - 2022 (Alpine 3.16 Switches
root:!toroot:*): Inmusl/shadowenvironments without PAM, prefixing an account hash with!locks the entire account, blocking SSH public-key logins as well as passwords. In 2022 (commit fbe926af), Alpine 3.16 changed the default root entry fromroot:!toroot:*so administrators could log in via SSH keys without PAM, assuming*would continue to forbid password authentication.
How OpenSSH 10.6p2 Fixes the Flaw
In the OpenSSH 10.6p2 release notes, maintainers state that they consider the root cause to lie outside sshd (in musl’s non-NULL error return), but applied a defensive workaround in sshd (commit 4353fdc43) to make exploitation impossible:
/* From OpenSSH 10.6p2 auth-passwd.c (commit 4353fdc43) */
#define MIN_PASSWORD_HASH_LEN 4
#define MAX_PASSWORD_LEN 1024
/* ... inside sys_auth_passwd() ... */
ret = encrypted_password != NULL &&
strlen(pw_password) >= MIN_PASSWORD_HASH_LEN &&
strcmp(encrypted_password, pw_password) == 0;
freezero(pw_password, strlen(pw_password));
return ret;By requiring the stored password hash (pw_password) to be at least 4 characters long (MIN_PASSWORD_HASH_LEN), sshd refuses to match single-character sentinel tokens like "*". The patch also duplicates shadow_pw() strings with xstrdup() rather than holding a pointer into libc’s static getspnam() buffer, and scrubs the buffer with freezero() after comparison.
3. Affected Systems, Cloud Images, and Safe Configurations
Not every Linux server or Alpine container is exposed to CVE-2026-123158. Use the matrix below to triage your fleet rapidly:
| Environment / Configuration | Exposure Status | Architectural Reason |
|---|---|---|
Alpine Linux with default openssh-server + local password user | Vulnerable | Uses musl without PAM, defaults to PasswordAuthentication yes, and has a $6$ salt |
Alpine tiny-cloud images (3.18.11–3.24.3) once password set | Critical Risk | alpine:* user has passwordless doas (root); becomes exploitable once any $6$ hash exists |
OpenWrt / Buildroot / Yocto (musl) with openssh-server | Vulnerable | Exposed if built without PAM, password auth is enabled, and both * and $5$/$6$ exist |
Alpine containers (Docker / Kubernetes) without sshd | Not Affected | Most application containers do not run an SSH daemon (see our Docker Hardened Images guide) |
Debian, Ubuntu, RHEL, Rocky, Fedora, SUSE (glibc) | Not Affected | glibc / libxcrypt returns NULL or "*0" on error, never matching "*" |
Servers with PasswordAuthentication no (or cloud-init) | Not Affected | sshd rejects password authentication before calling sys_auth_passwd() |
openssh-server-pam with UsePAM yes | Not Affected | PAM handles authentication instead of sshd’s internal sys_auth_passwd() |
Accounts locked with ! in /etc/shadow (user:!:...) | Not Affected | Locked accounts are rejected before password hash comparison and never match "*" |
OpenWrt default SSH server (Dropbear) | Not Affected | Dropbear does not use OpenSSH’s pick_salt() / xcrypt() implementation |
Why Alpine tiny-cloud Images Face Indirect Root Compromise
On standard Alpine Linux installations, root ships with root:* in /etc/shadow, but OpenSSH’s default PermitRootLogin prohibit-password setting blocks direct password authentication for root (unless an administrator explicitly changed the setting to PermitRootLogin yes).
However, indirect root compromise is a critical risk on official Alpine cloud images built with tiny-cloud (including AWS AMIs, Azure VHDs, and qcow2 artifacts from 3.18.11 through 3.24.3):
- Those
tiny-cloudimages create a defaultalpineuser with*in/etc/shadowand grantalpinepasswordlessdoasprivileges (permit nopass :wheel as root). - On first boot, if no account has a password set, no
$5$or$6$hash exists in/etc/shadow, sopick_salt()falls back to the 2-character DES salt"xx"(which truncates rather than failing at 256 bytes). - As soon as an administrator sets a password for any local account (or
user-dataprovisions a user withhashed_passwd), a$6$hash is written to/etc/shadow. - An unauthenticated attacker can then log in over SSH as
alpineusing a 300-character password and immediately executedoas su -to gain fullrootcontrol.
4. Patched OpenSSH and Alpine Linux Package Versions
Alpine Linux published fixed openssh packages on November 5, 2026, for all active branches (3.22 through 3.24 and edge) as well as end-of-support branches all the way back to Alpine 3.16:
| Alpine Branch | Support Status | First Fixed openssh Package | Fixed Point Release ISO / Cloud Image |
|---|---|---|---|
| edge | Rolling development | 10.6_p2-r0 | Rolling |
| 3.24 | Active support | 10.3_p1-r2 | Alpine 3.24.4 |
| 3.23 | Active support | 10.2_p1-r1 | Alpine 3.23.8 |
| 3.22 | Active support | 10.0_p1-r11 | Alpine 3.22.8 |
| 3.21 | End of support (Nov 1, 2026) | 9.9_p2-r1 | Alpine 3.21.10 |
| 3.20 | End of support (backported) | 9.7_p1-r6 | Upgrade via apk |
| 3.19 | End of support (backported) | 9.6_p1-r3 | Upgrade via apk |
| 3.18 | End of support (backported) | 9.3_p2-r4 | Upgrade via apk |
| 3.17 | End of support (backported) | 9.1_p1-r7 | Upgrade via apk |
| 3.16 | End of support (backported) | 9.0_p1-r6 | Upgrade via apk |
If you compile Portable OpenSSH from source on a musl-based distribution (such as custom OpenWrt, Buildroot, or Yocto images), upgrade directly to OpenSSH 10.6p2 or apply commit 4353fdc43.
5. Remediation and Threat Hunting Playbook
Step 1: Audit Exposure and Upgrade OpenSSH
First, verify your installed openssh-server package version and check whether your host meets the exposure conditions. Then update all packages and restart sshd because apk upgrade does not automatically restart the running SSH daemon:
# 1. Check the currently installed openssh package version on Alpine
apk info -v openssh-server
# 2. Check if any accounts have '*' in /etc/shadow alongside a $5$ or $6$ hash
awk -F: '$2 == "*" {print "Passwordless (*) account:", $1} $2 ~ /^\$[56]\$/ {print "SHA-crypt ($5$/$6$) account:", $1}' /etc/shadow
# 3. Upgrade all packages to the patched release and restart sshd
apk upgrade -U -a
rc-service sshd restartStep 2: Disable Password Authentication (Immediate Workaround)
Enforcing SSH key-only logins aligns with the Principle of Least Privilege and eliminates the sshole attack vector even on unpatched hosts. Before running the commands below, confirm that your SSH key authentication works and keep your current SSH terminal open until you verify a new connection in a separate window:
# 1. Create a drop-in config (read by default on Alpine 3.19+)
mkdir -p /etc/ssh/sshd_config.d
echo 'PasswordAuthentication no' > /etc/ssh/sshd_config.d/00-no-passwords.conf
# 2. Force PasswordAuthentication no across /etc/ssh/sshd_config (including Match blocks)
sed -i.bak -e '1i PasswordAuthentication no' \
-e 's/^\(\s*PasswordAuthentication[^y#]*\)yes/\1no/i' \
/etc/ssh/sshd_config
# 3. Validate syntax, restart sshd, and confirm effective configuration
sshd -t && rc-service sshd restart
sshd -T | grep -i passwordauthenticationConfirm that the final command outputs passwordauthentication no.
Step 3: Hunt for Indicators of Compromise in SSH Logs
Because a successful sshole exploit completes on the first attempt using standard SSH password authentication, it does not generate a burst of failed login alerts. Instead, defenders must look for a successful password login (Accepted password for) on an account that has no password set (*):
# 1. List all accounts currently configured with '*' in /etc/shadow
awk -F: '$2 == "*" {print $1}' /etc/shadow
# 2. Search syslog for any accepted password logins (especially for alpine, root, or key-only users)
grep -E "sshd\[.*\]: Accepted password for" /var/log/messages*
# 3. Audit doas privilege escalations, newly created accounts, and SSH authorized_keys
grep "doas:" /var/log/messages*
find /root /home -name "authorized_keys" -ls 2>/dev/nullIf /var/log/messages records Accepted password for an account whose /etc/shadow entry is *, or if log rotation prevents you from ruling out an unauthorized login on an internet-exposed host, treat the machine as compromised, isolate the workload, rotate all credentials and host keys, and rebuild from a patched image (3.21.10, 3.22.8, 3.23.8, or 3.24.4).
Conclusion: Why AI-Driven Bug Discovery Is Shrinking Patch Windows
Beyond the immediate urgency for Alpine Linux administrators, CVE-2026-123158 highlights a broader shift in how decades-old vulnerabilities are being uncovered in 2026. As we analysed in our AI-era CVE exploitation trends report, security researchers are increasingly pairing automated fuzzing harnesses with AI agent swarms to test overlooked integration boundaries. To find sshole, Özgün Kültekin compiled sshd across every permutation of glibc, musl, PAM, and shadow configurations and used agent swarms to fire roughly 17,600 anomalous authentication attempts against the “boring glue code” between OpenSSH and libc.
In the OpenSSH 10.6p2 release announcement, maintainer Damien Miller explicitly noted that the OpenSSH team has seen multiple cases where a bug identified with AI assistance was independently rediscovered by another researcher within hours prompting OpenSSH to abandon long embargoes in favour of immediate single-fix releases. For infrastructure teams, the lesson is unmistakable: patch openssh and restart sshd today, and enforce PasswordAuthentication no across every server so password-handling quirks never reach production.
To further enhance your cloud security and implement Zero Trust, contact me on LinkedIn Profile or [email protected].
FAQ
Frequently Asked Questions (FAQ)
What is the sshole vulnerability (CVE-2026-123158)?
CVE-2026-123158, nicknamed sshole (*sshole), is a high-severity (CVSS 8.1) password authentication bypass in OpenSSH versions prior to 10.6p2. On Linux systems using musl libc without PAM most notably Alpine Linux an attacker can log in to passwordless accounts (marked with * in /etc/shadow) by sending any password between 257 and 1,024 bytes long.
Does CVE-2026-123158 affect Ubuntu, Debian, or RHEL servers?
No. Standard Ubuntu, Debian, Red Hat Enterprise Linux (RHEL), Rocky Linux, and Fedora distributions use glibc (or libxcrypt) and authenticate SSH sessions through PAM. OpenSSH maintainer Damien Miller confirmed that glibc-based Linux systems, PAM-enabled servers, and non-Linux systems are not affected by CVE-2026-123158.
Are Alpine Linux Docker containers vulnerable to sshole?
Most Alpine-based Docker and Kubernetes containers are not affected because they do not install or run the sshd daemon. An Alpine container is vulnerable only if it runs openssh-server without PAM, leaves PasswordAuthentication set to yes, has an account with * in /etc/shadow, and contains at least one other local user with a $5$ or $6$ password hash.
Why does a 257-character password bypass OpenSSH authentication on musl?
When an account has * in /etc/shadow, OpenSSH borrows a $5$ or $6$ salt from another local user to prevent timing-based user enumeration (CVE-2016-6210). However, musl libc rejects passwords longer than 256 bytes for SHA-256 and SHA-512 hashes and returns the string "*" on error instead of NULL. OpenSSH compares that returned "*" against the stored "*" in /etc/shadow and accepts the login.
Can attackers gain root access on Alpine Linux using CVE-2026-123158?
Direct SSH password login as root is blocked by default because PermitRootLogin prohibit-password is enabled unless an administrator changed it to yes. However, on official Alpine tiny-cloud images from 3.18.11 through 3.24.3, an attacker can log in as the passwordless alpine user (once any local account has a $6$ password hash) and escalate to root via passwordless doas.
How do I fix CVE-2026-123158 on Alpine Linux?
Run apk upgrade -U -a to install the patched openssh package for your Alpine branch (such as 10.3_p1-r2 on Alpine 3.24 or 10.6_p2-r0 on edge), and then run rc-service sshd restart so the running daemon reloads the patched binary. If you cannot upgrade immediately, set PasswordAuthentication no in /etc/ssh/sshd_config and restart sshd.
Resources
- Alpine Linux Security Advisory: openssh-server password authentication bypass (2026-11-05)
- OpenSSH Release Notes: Portable OpenSSH 10.6p2 Advisory (2026-11-05)
- Vulnerability Research & PoC: *sshole Technical Write-Up by Özgün Kültekin (Wakefield)
- Upstream Patch: OpenSSH Commit 4353fdc43 (
MIN_PASSWORD_HASH_LEN) - Related Analysis: PHP2Shell (CVE-2026-109618 & CVE-2026-109619): Critical PHP RCE Patch Guide
- Related Analysis: Node.js Brotli RCE (CVE-2026-111497): Patch Guide



