On November 5, 2026, Özgün Kültekin published *sshole: OpenSSH running on musl libc has accepted logins for accounts with no password since 2016. Under the conditions below, an attacker who can reach sshd can authenticate to an eligible key-only account using an overlong password. The official Alpine tiny-cloud images include an alpine user with passwordless doas, but are safe on first boot: exploitation requires at least one local account with a real SHA-crypt password hash. Direct root login additionally requires PermitRootLogin yes; the default PermitRootLogin prohibit-password blocks that path. OpenSSH shipped a fix the same day in 10.6p2, and Alpine published patched packages for every branch, including unsupported ones, on November 5.
We reproduced the flaw in a lab to verify the published conditions and examine practical testing and detection limits. We built two environments with the pre-fix OpenSSH pinned by exact package version (10.3_p1-r1, the revision before Alpine's fix): a full Alpine 3.24 VM and an Alpine Docker container with port 22 published. The bypass worked in both, at the documented boundary. Our tests confirmed the failed-first-attempt behavior described in the original disclosure and the documented protection from PAM. They also highlighted a limit in our client/askpass setup and false positives from version-based detection after a distribution backport.
This matters for CI/CD. Alpine is one of the most-used container base images, and sshd appears in images built for remote debugging. The exposure is narrower than the headline suggests, and the sections below give the exact conditions, the test results, and the steps for runners, container images, and any Alpine hosts you operate.
At a glance
- CVE: CVE-2026-123158 (GHSA-4fcc-vm97-gx3x, CVSS v3 8.1 High; the GitHub advisory is unreviewed, and the OpenSSH and Alpine advisories currently cite no CVE)
- Component: sshd on musl libc without PAM: Alpine, OpenWrt with openssh installed (not the default Dropbear), Buildroot, Yocto with TCLIBC=musl
- Impact: an unauthenticated network attacker can log in as an account whose shadow password field is
*, provided SSH policy permits that account to authenticate and all other exploit conditions hold - Exposed configurations: unpatched OpenSSH on Alpine 3.16 and later, with PAM disabled,
PasswordAuthentication yes, an eligible*account, and at least one real SHA-crypt hash on the host - Fix: OpenSSH 10.6p2 upstream; patched packages on every Alpine branch back to 3.16. Restart sshd after upgrading.
- Exploited in the wild: the original disclosure and vendor advisories reviewed on November 6, 2026 do not report confirmed exploitation in the wild. Public PoCs exist, so scanning should be expected.
Check whether you are affected: a host is exposed only if every one of the following holds. It runs musl libc, not glibc, with an unpatched sshd. sshd is built or configured without PAM. PasswordAuthentication is yes. At least one account permitted to log in via SSH has * as its shadow password field. For root, that also requires PermitRootLogin yes. And at least one local account has a real $5$ or $6$ hash, which sshd borrows a salt from. Systems missing any one of these conditions are not exposed through this flaw.
How the Bug Works
No single component is the bug. Three decisions made between 2012 and 2016 combine into an authentication bypass.
- musl's
crypt()returns"*"on failure (2012) instead ofNULL. That string collides with the Unix convention of storing*in the shadow password field to mean no password can ever match the account. - musl caps crypt input at 256 bytes (2012), as a defense against CPU exhaustion. A longer password makes crypt fail, which returns
"*". - OpenSSH's non-PAM password path borrows a salt (2016, part of the fix for CVE-2016-6210) for users with no valid hash. sshd hashes the submitted password with the borrowed salt and compares the result to the stored field.
With a password longer than 256 bytes, within sshd's accepted input length, against an eligible account whose stored field is *: crypt fails on length, returns "*", and the comparison succeeds. sshd accepts the login. The account has no password.
The upstream fix, commit 4353fdc43 in OpenSSH 10.6p2, refuses to compare stored fields shorter than a plausible hash. Upstream's position is that the root cause is not in OpenSSH, but that OpenSSH can avoid it.
The Lab
Two environments, both built from verified Alpine media with the pre-fix OpenSSH pinned by exact package version:
- A full Alpine 3.24 VM (QEMU, aarch64) with a key-only user whose shadow field is
*, the exploit target, and a second user with a real SHA-512 hash, the salt donor. - An Alpine Docker image built the same way, with port 22 published, because containers are the likelier exposure for most teams.
Attacks ran from outside each environment over the network, using the stock OpenSSH client with an askpass helper. The test passwords used ASCII A characters, so each character was one byte.
Results
Against the vulnerable sshd, the boundary matched the disclosure:
[T1 alpine + wrong, then 256 x A ] REJECTED
[T2 alpine + wrong, then 257 x A ] ACCEPTED -> uid=1000(alpine)
[T3 alpine + wrong, then 300 x A ] ACCEPTED -> uid=1000(alpine)
[T4 alpine + 300 x A, 1st attempt] REJECTED
[T7 authsource + 300 x A ] REJECTED (real password hash - immune)
[T11 alpine + wrong, then 1023 x A] ACCEPTED
The auth log shows the result: a successful password login for an account with no password.
sshd-session[1926]: Failed password for alpine from 10.0.2.2 port 59008 ssh2
sshd-session[1926]: Accepted password for alpine from 10.0.2.2 port 59008 ssh2
After upgrading to 10.3_p1-r2 and restarting sshd, the same attempts were rejected and normal logins continued to work. In the Docker container, the same matrix produced the same results: same boundary, same first-attempt behavior, same immunity for accounts with real password hashes.
The Bypass Requires a Failed Attempt First
In our tests, a password longer than 256 bytes sent as the first authentication attempt in a connection was rejected. The bypass succeeds on a second or later attempt in the same connection, and the first attempt can be anything, including another long password. We verified this on the pinned 10.3p1 in both the VM and the container; other versions may differ.
This has three practical implications:
- The Alpine advisory describes the attack as taking one connection that "works every time, and needs no retries." That describes connections, not individual password prompts. In our tested configuration, a scanner that sends only one long password per connection can incorrectly report vulnerable hosts as safe.
- The original disclosure already documents the failed first attempt. The finder's repository describes two prompts: a throwaway password first, followed by the long password. Our VM and container results independently confirmed that behavior for the pinned version.
- The detection signature is a pair: a failure followed by an
Accepted passwordfor the same passwordless account, in the same session. Alerting onAccepted passwordfor passwordless accounts already covers this. The failed sibling event is part of the same signature.
Our Client/Askpass Setup Limited Tests to 1023 Bytes
The Alpine advisory documents a working range of 257 to 1024 bytes. In our runs, ASCII passwords of 1024 and 1025 bytes failed with a connection error, while sshd stayed healthy and accepted 1022- and 1023-byte passwords moments later. In our tested OpenSSH client/askpass setup, the failure happened before the password reached the server. The largest password delivered successfully through that setup was 1023 bytes; this is a test-harness limitation, not a universal limit for every OpenSSH client. We did not validate the server-side boundary through a different client. OpenSSH's password-authentication code separately defines MAX_PASSWORD_LEN as 1024 and rejects passwords longer than that. Keep these client and server limits distinct when interpreting test results.
UsePAM yes Blocks the Bypass on a Vulnerable sshd
The advisories state that PAM setups are not affected because PAM performs the password check instead of sshd's internal crypt path. We tested this directly with a third image: the same pre-fix OpenSSH binary, in the PAM flavor, with UsePAM yes.
[F1 alpine + wrong, then 300 x A ] REJECTED
[F2 alpine + wrong, then 257 x A ] REJECTED
[F3 authsource + correct password ] ACCEPTED
The bypass was blocked and normal logins worked, on musl, with the vulnerable code still installed. For hosts that cannot upgrade immediately, the PAM flavor with UsePAM yes is a working mitigation.
Version Checks Report Patched Systems as Exposed
The community check.sh from the disclosure repository decides whether the fix is present based on the version sshd reports. Alpine backports the fix without changing that string. Our host with 10.3_p1-r2 installed still reported OpenSSH_10.3p1, and the script reported the host as "EXPOSED. anyone can log in as: alpine" while the attack itself was rejected.
This generalizes beyond one script: on distributions that backport, version strings do not establish patch state. Ask the package manager, with apk info -v openssh-server (or apk info -v openssh-server-pam for the PAM package), or test behavior. Compare the installed package revision with the vendor's fixed-version list, rather than relying on the upstream version banner alone.
Fixed Versions
Upstream: OpenSSH 10.6p2 (November 5, 2026, commit 4353fdc43). Alpine published patched packages on November 5 for every branch, including unsupported ones:
- Alpine edge:
10.6_p2-r0 - Alpine 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 - Alpine 3.19 through 3.16: patched packages were published despite end-of-life status. See the Alpine advisory for exact revisions.
Upgrading the package does not replace the running daemon. Restart sshd after the upgrade.
What to Do Now
1. Alpine or musl hosts you operate
Upgrade openssh and restart sshd, then review auth logs for Accepted password for against key-only accounts whose shadow field is *. Investigate unexpected successes as possible compromise, including any preceding failure in the same session. An empty shadow field is a different account configuration and is not the * collision described here.
2. Container images
We verified that the v3.24 package index currently publishes only the patched openssh-server, so a fresh apk add openssh-server gets the fix. The exposure is images built or pinned before November 5, 2026: cached CI layers, internal registry copies, and mirrored APKs. Rebuild those from current repositories, and check whether sshd is needed in the image at all.
3. Runners and CI
GitHub-hosted Ubuntu runners and glibc-based self-hosted runners are not affected. The exposure is Alpine-based runner containers and images that install and expose sshd. Audit for those, and set PasswordAuthentication no wherever keys are an option.
4. Hosts you cannot upgrade today
Two mitigations, both verified in the lab: set PasswordAuthentication no, or use the PAM flavor with UsePAM yes. Disabling password authentication preserves key-based logins; the PAM configuration can preserve legitimate password logins. Validate the replacement login method before closing your current session, check the SSH configuration, and restart sshd for changes to take effect.
5. Verify by behavior, not version strings
On distributions that backport fixes, sshd -V cannot establish whether the fix is present. Ask the package manager, or test in a lab.
References
- sshhole.com: the original disclosure
- OpenSSH release notes: 10.6p2
- Alpine Linux security advisory: openssh-server password authentication bypass
- oz9un/sshole: PoC, check tooling, and disclosure timeline
- GitHub Advisory GHSA-4fcc-vm97-gx3x (CVE-2026-123158)
- Orca Security: *sshole analysis
- Hacker News discussion



