SecurityOpenSSHAlpine LinuxDevOpsVulnerabilities

*sshole OpenSSH Bypass: How to Check and Patch Alpine and musl Hosts

person
LaunchBoosts Research Desk·AI-assisted research
8 min read

Researched and drafted with AI assistance from the 8 public sources listed at the end of this article, then published after automated editorial checks. Spotted an error? Tell us at support@launchboosts.com.

*sshole OpenSSH Bypass: How to Check and Patch Alpine and musl Hosts — LaunchBoosts

*sshole is an OpenSSH authentication bypass. On Linux systems that use musl libc and run sshd without PAM, it lets an attacker log in to accounts that were never supposed to accept a password. Any password of 257 to 1,024 bytes works. Alpine Linux is the main target, and OpenWrt, Buildroot and Yocto builds may also be exposed. The fix shipped in OpenSSH 10.6p2 on November 5, 2026, and Alpine pushed patched packages to its stable branches the same day. Debian, Ubuntu, Fedora and anything else that uses PAM or glibc is not affected.

The bug reached the top of Hacker News, and it matters to the people who read this site. Lots of small teams run Alpine VMs, sshd inside containers, or cheap embedded boxes, often with password authentication still at its default setting. This guide covers who is actually exposed, how to check in a few minutes, what to patch, and how to look for signs someone already got in.

What *sshole is and why it works

The researcher Özgün Kültekin published the bug at sshhole.com with a proof of concept and a detection script in a GitHub repository. It is tracked as CVE-2026-123158. According to the CVE record, it was published on November 5, 2026 at 15:46 UTC with a CVSS 3.1 score of 8.1 (High, network attack vector, high attack complexity, no privileges needed). The record classifies it as CWE-394, "Unexpected Status Code or Return Value". Some early coverage, including Orca Security's write-up, said no CVE had been assigned yet. The ID appeared later that day.

No single line of code is broken. The bypass comes from two decisions, years apart, that interact badly:

  1. musl's crypt() returns "*" on failure, not NULL. musl made this change in 2012, the researcher's write-up says. In the same year, musl's SHA-512 crypt got a 256-byte maximum key length as DoS protection, so longer passwords make hashing fail.
  2. sshd hashes passwords even for accounts with no usable hash. BleepingComputer explains that this came from the 2016 fix for CVE-2016-6210, a timing-based username enumeration bug. To keep timing constant, sshd hashes the submitted password for accounts like those with * in /etc/shadow, using a salt borrowed from another account.

Put the two together. An oversized password makes musl's crypt() fail and return "*". sshd compares that string with the account's stored *, they match, and the login succeeds. Accounts with real password hashes are not bypassed. The bug only hits accounts whose shadow field is literally *, which are the ones admins think of as locked or key-only.

Kültekin found the bug with AI agents that ran about 17,600 authentication tests across OpenSSH build configurations, malformed hashes and oversized passwords, per BleepingComputer. Every build behaved the same way except musl without PAM. The OpenSSH 10.6p2 release notes call the change a "critical security workaround". They note that the root cause sits outside sshd but can be avoided there.

Who is exposed: the four conditions

A host is exploitable only when all of these are true. BleepingComputer, Orca and the researcher's script all list the same conditions:

Condition Typical on Alpine? How to check
sshd runs on musl libc Yes (Alpine always uses musl) cat /etc/alpine-release or ldd $(which sshd)
sshd built without PAM, or UsePAM no Yes, the default openssh-server package has no PAM sshd -T | grep usepam
PasswordAuthentication enabled Yes, it's the OpenSSH default sshd -T | grep passwordauthentication
At least one account with * in /etc/shadow, and at least one local account with a real $5$ or $6$ hash Often awk -F: '$2=="*"' /etc/shadow and grep -E ':\$[56]\$' /etc/shadow

The second account condition is easy to miss. sshd borrows a salt from a real SHA-256 or SHA-512 hash on the system to drive the failing code path. On a fresh box where nobody has set a password, the bug can't be triggered, and the write-up says such systems aren't affected.

Which accounts are at risk

Orca lists these typical targets:

  • root on Alpine 3.16 and later. Alpine changed root's shadow field to * in 3.16. OpenSSH's default PermitRootLogin prohibit-password still blocks password logins as root, so root is directly reachable only if you've changed that setting.
  • Key-only deploy and service users. CI deploy accounts, backup users and git users created without a password.
  • Directory users that come from nslcd, winbind or sssd.
  • The alpine user on tiny-cloud images. This is the worst case. BleepingComputer reports that Alpine's official AWS and Azure images ship a default alpine account with passwordless doas, so getting into that account gives an attacker root.

Who is not affected

glibc distributions (Debian, Ubuntu, Fedora, RHEL and derivatives), any sshd that authenticates through PAM, Dropbear, and non-Linux systems such as OpenBSD. On Alpine, a server with password authentication already turned off is not exploitable either.

What about containers? The official alpine base image doesn't run sshd. You're exposed only if your own Dockerfile installs openssh-server and leaves password login on, which is common in "SSH into the container" dev images and some bastion setups.

Fixed versions

Upstream OpenSSH fixed the bug in 10.6p2, released November 5, 2026, according to the release notes. Alpine backported the fix instead of moving every branch to 10.6. Orca and Konfirmity's advisory summary give these fixed packages:

Alpine branch Fixed openssh package Support status
edge 10.6_p2-r0 Rolling
3.24 10.3_p1-r2 Supported
3.23 10.2_p1-r1 Supported
3.22 10.0_p1-r11 Supported
3.21 9.9_p2-r1 Supported
3.20 9.7_p1-r6 Out of support
3.19 9.6_p1-r3 Out of support

These match the latest versions on Alpine's security tracker for edge through 3.19. For 3.16 to 3.18, Konfirmity lists fixed builds that the tracker doesn't show yet when we checked. If you run one of those old releases, don't assume apk upgrade patched you. Check the installed version, and plan to move to a supported branch. Until then, disable password authentication.

If you build OpenSSH yourself for Buildroot, Yocto or custom musl images, move to 10.6p2. The researcher's repo also includes the upstream commit as a patch and says it applies to OpenSSH 7.3p1 and later.

How to check and patch a host in 10 minutes

1. Confirm exposure

The quickest way is the researcher's check.sh, run as root. It reports the libc, the sshd version, whether sshd has PAM, the effective PasswordAuthentication value, and both account conditions, then prints "EXPOSED" or names the condition that's missing. Read the script before running it as root. It's short.

To check by hand, use the commands in the table above. Use sshd -T (the effective config) rather than reading sshd_config, because Match blocks and drop-in files can turn password login back on for some users or addresses.

2. Patch and restart

On Alpine:

apk upgrade -U openssh
rc-service sshd restart
apk info -v | grep openssh

The restart matters. Orca notes that upgrading the package doesn't replace the running daemon. Keep an existing SSH session open while you restart so a mistake doesn't lock you out.

3. If you can't patch today, turn off password login

echo 'PasswordAuthentication no' > /etc/ssh/sshd_config.d/00-no-passwords.conf
sshd -t && rc-service sshd restart
sshd -T | grep passwordauthentication

First confirm that key login works for every account you need. Then search your config for Match blocks that set PasswordAuthentication yes. This mitigation is the researcher's own recommendation, and it's good practice even after you patch.

4. Fix the source, not just the running fleet

Old cloud images, golden AMIs and container base layers still contain the vulnerable package, and every new instance starts out exposed. Rebuild your images, bump pinned openssh versions in Dockerfiles, and re-run your provisioning. Konfirmity specifically flags tiny-cloud images from 3.18.11 to 3.24.3. Also, Konfirmity says the NVD entry hadn't been analyzed as of November 5, so scanners that rely on NVD enrichment may not flag the issue yet.

Hunting for signs of exploitation

The public write-up has enough detail to reproduce the attack. Orca says no exploitation in the wild had been reported when it published, but internet-facing Alpine hosts with password login enabled will be scanned soon if they aren't already.

The useful signal is a successful password login to an account that has no password:

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

Compare the usernames in the two outputs. BleepingComputer gives the same grep for Alpine's default syslog location. If you forward logs to a central system, search there too, because an attacker with root can edit local logs.

If you find a match, Orca's advice is to treat the host as compromised. In practice:

  1. Isolate the host and keep its logs.
  2. Review doas usage, new user accounts, and changes to authorized_keys files.
  3. Rebuild from a patched image instead of trying to clean the system.
  4. Rotate every credential the host held: deploy keys, cloud API tokens, database passwords, and any LLM or SaaS API keys in environment files.

What this changes for small teams

The bigger lesson isn't specific to Alpine. "Key-only" and "locked" are policies you assume, and they can fail. The * in /etc/shadow was supposed to mean "no password can match", and an edge case in a libc made it mean the opposite. Three habits remove whole classes of bugs like this:

  • Turn off PasswordAuthentication everywhere unless you have a documented reason to keep it. With password login off, *sshole doesn't matter, whatever your libc.
  • Don't expose sshd to the internet. Put it behind a VPN, a bastion, or an identity-aware proxy, or replace it with your cloud provider's session manager.
  • Treat base images as dependencies. Pin them, scan them, and rebuild them on a schedule so a fix like this reaches every running instance within days.

If you're comparing tools to help with this, such as image scanners, config auditors, or AI assistants that review infrastructure code, the AI coding assistants section of the LaunchBoosts directory is a reasonable place to start.

What to do now and what to watch

Today: list every musl-based host and image that runs sshd, run the check, patch and restart, and turn off password login. This week: rebuild cloud images and container base layers, and search centralized logs for password logins to * accounts going back as far as you keep them.

Things to watch next:

  • OpenWrt, Buildroot and Yocto advisories. These embedded ecosystems were named as possibly affected, but none of the coverage we read reported a confirmed fix. Router and IoT firmware tends to lag well behind.
  • NVD enrichment and scanner signatures for CVE-2026-123158. Until they land, some vulnerability dashboards will show clean results on hosts that are still exposed.
  • Whether musl changes crypt(). OpenSSH's fix works around the problem in sshd. Other software that compares crypt() output against stored hashes on musl may have similar edge cases, and the researcher's write-up suggests that's worth checking.

Frequently asked questions

Is Ubuntu or Debian affected by the *sshole vulnerability?

No. The bug needs musl libc, and Debian, Ubuntu, Fedora and other glibc distributions don't use it. Any system where sshd authenticates through PAM is also unaffected, and so are Dropbear and OpenBSD.

Which OpenSSH version fixes *sshole (CVE-2026-123158)?

Upstream OpenSSH 10.6p2 fixes it. It was released on November 5, 2026. Alpine backported the fix to its stable branches, for example openssh 10.3_p1-r2 on 3.24 and 10.2_p1-r1 on 3.23. You have to restart sshd after upgrading, because the running daemon keeps the old code.

Are official Alpine Docker images vulnerable?

The base alpine image doesn't run an SSH server, so it isn't exposed on its own. You're at risk if you built an image that installs openssh-server, leaves password authentication on, and has a key-only or locked account next to an account with a real password. Rebuild those images with the patched package.

How do I know if my server was already exploited through *sshole?

Search your auth logs for 'Accepted password for' and compare each username against /etc/shadow. A successful password login for an account whose password field is '*' should never happen. Treat that host as compromised: rebuild it and rotate any secrets it held.

Can I mitigate *sshole without upgrading?

Yes. Set 'PasswordAuthentication no' in your sshd configuration, check it with 'sshd -t', then restart sshd. Make sure key-based login works first, and check that no Match block turns password login back on for some users.

Sources

  1. *sshole: researcher write-up by Özgün Kültekin (sshhole.com)— sshhole.com
  2. CVE-2026-123158 record (CVE.org)— cve.org
  3. OpenSSH release notes (10.6p2)— openssh.org
  4. OpenSSH flaw lets attackers log into password-disabled Linux accounts (BleepingComputer)— bleepingcomputer.com
  5. *sshole: OpenSSH Authentication Bypass Gives Attackers Root on Alpine Linux (Orca Security)— orca.security
  6. oz9un/sshole: detection script, PoC and patch (GitHub)— github.com
  7. Alpine OpenSSH password bypass advisory summary (Konfirmity)— konfirmity.com
  8. Alpine Linux security tracker: openssh— security.alpinelinux.org
person

LaunchBoosts Research Desk

AI-assisted research

Explainers on software and AI industry trends, drafted with AI assistance from the public sources cited in each article and published after automated editorial checks for length, independent sourcing and originality.