Critical PHP and Node.js flaws php2shell + node2shellTest my domain
OpenSSHAlpine LinuxSSHAuthenticationCVEVulnerability

CVE-2026-123158: OpenSSH password authentication bypass on Alpine Linux

CVE-2026-123158 (sshole, CVSS 8.1): OpenSSH password authentication bypass on Alpine and other musl Linux systems without PAM. Affected systems, fixes.

by 15 min read
CVE-2026-123158: OpenSSH password authentication bypass on Alpine Linux

Background

On 5 November 2026, OpenSSH released a fix, 10.6p2, for an sshd vulnerability reported the day before by Özgün Kültekin, a researcher at Wakefield. It is tracked as CVE-2026-123158, and the researcher nicknamed it "sshole".

The flaw allows a password login to an account that has no password. It only affects Linux systems built on the musl C library whose sshd checks passwords without going through PAM.

That is Alpine Linux's default configuration, so Alpine carries most of the risk. Debian, Ubuntu, RHEL and other glibc distributions are not affected.

Alpine published its advisory the same day, with fixed packages for every branch since 3.16. No exploitation had been reported at the time of writing.

Technical summary

ItemValue
IdentifierCVE-2026-123158, published on 5 November 2026 by MITRE
Nickname"sshole", spelled "*sshole" by the researcher and "SSHhole" in part of the press
Componentsshd, password authentication without PAM (auth-passwd.c, xcrypt.c)
PlatformsLinux with musl: mainly Alpine, but also Buildroot, Yocto or OpenWrt when they ship OpenSSH
ClassCWE-394, unexpected status code or return value
CVSS 3.18.1, vector AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H (MITRE, also used by Red Hat). Not yet analyzed by NVD
SSVC (CISA)Exploitation: poc; automatable: no; technical impact: total
Affected versionsOpenSSH portable before 10.6p2, under the conditions described below
FixOpenSSH 10.6p2 (commit 4353fdc, "avoid password authn bypass"); Alpine packages from 3.16 to edge
DiscoveryÖzgün Kültekin (Wakefield), reported to OpenSSH on 4 November 2026
ExploitationNone observed as of 6 November; not in the KEV catalog

The 8.1 score comes from an attack complexity rated high (AC:H). OpenSSH, for its part, calls the fix "critical" in its release notes.

We read that AC:H as a reflection of configuration preconditions rather than technical difficulty. On a host that meets them, Alpine's advisory describes a deterministic attack that succeeds on the first attempt.

For an affected server, we would therefore treat it as a critical flaw. We discuss this kind of gap between score and actual risk in our article on vulnerability prioritization.

Affected systems

Alpine's advisory sets four conditions, all of which must be met:

  1. sshd checks passwords without PAM. That is the case for Alpine's openssh-server package; the openssh-server-pam variant is only affected with UsePAM no.
  2. Password authentication is enabled (PasswordAuthentication yes, OpenSSH's default).
  3. At least one account has * as its password field. On Alpine, that includes root in base images, accounts created for key-only login, and some directory-backed accounts.
  4. At least one other local account has a real password hash, in $5$ or $6$ format.

Not affected:

  • glibc distributions (Debian, Ubuntu, RHEL and derivatives, Fedora), as well as macOS and OpenBSD;
  • any sshd that checks passwords through PAM;
  • servers configured with PasswordAuthentication no;
  • accounts locked with ! rather than *;
  • Dropbear, OpenWrt's default SSH server, and other password login programs, according to musl's maintainer;
  • Alpine containers that do not run sshd, which is the vast majority.

The root account

In Alpine images, root has had * as its password since 3.16. It remains protected by the default PermitRootLogin prohibit-password, which refuses any password login for root.

A server where that directive has been set to yes, on the other hand, exposes root directly. It is the first setting we would check.

Official cloud images

Alpine's "tiny-cloud" images (qcow2, VHD, AMI), from 3.18.11 to 3.24.3, create an alpine user. Its password field is *, it has passwordless doas, and it has the same name on every instance.

A freshly booted instance is not vulnerable, since no account has a real password. It becomes vulnerable as soon as a $6$ hash appears on the machine:

  • a password set for console access;
  • a hashed_passwd passed in user-data;
  • a service account created by hand.

In our view this is the most serious case, because the missing condition comes from an entirely routine administration task.

Images built from 3.21.10, 3.22.8, 3.23.8 and 3.24.4 include the fix. Instances already running have to be updated one by one. Alpine notes that images using cloud-init write PasswordAuthentication no and are not affected.

Containers and embedded systems

An Alpine container is only exposed if it runs an SSH server with passwords enabled: jump containers, SFTP servers, "SSH in a box" images. It is rare, but it happens.

Updating the package inside the container is not a lasting fix, since the next redeployment brings back the old version. The image has to be rebuilt from a fixed base.

Buildroot or Yocto systems, and OpenWrt routers where OpenSSH has replaced Dropbear, are in the same situation as Alpine if they meet the four conditions. For a device whose firmware you do not control, ask the vendor and disable password authentication if the interface allows it.

How it works

To find the flaw, Özgün Kültekin built sshd in every possible combination: glibc or musl, with or without PAM, with or without a shadow file. He then put each build through about 17,600 unusual login attempts, generated with AI agents.

Only one combination behaved differently from the others: musl without PAM. The defect comes from three choices made separately, over ten years:

  • In 2012, musl made crypt() return the string * on failure, rather than NULL. Three weeks later, the library added SHA-crypt, with a key limited to 256 bytes; beyond that, crypt() fails.
  • In 2016, OpenSSH fixed CVE-2016-6210, an account enumeration through response timing. Since then, sshd computes a hash even for an account with no valid one, borrowing the salt of another account on the system. That is where the fourth condition comes from.
  • In 2022, Alpine 3.16 gave root * instead of !. Without PAM, ! also blocked key-based login, an issue open since CVE-2019-5021.

Without PAM, sshd hashes the password it receives and compares the result, string to string, with the field in /etc/shadow. Under musl, a password longer than 256 bytes makes that computation fail, and it returns *. If the account's field is also *, the comparison succeeds.

Under glibc, crypt() reports the failure differently and sshd already rejects that case. With PAM, crypt() is never called for an account set to *.

The fix adds a guard in sys_auth_passwd(): no match is accepted if the stored hash is shorter than four characters (MIN_PASSWORD_HASH_LEN). No real hash is that short, while the "no password" markers (*, !, x) all are.

The two projects disagree on who is responsible:

  • OpenSSH writes: "We consider the root cause of this bug to be outside sshd, but it is exploitable via sshd and can be avoided there";
  • Rich Felker, musl's maintainer, says it is "not a bug in musl just an erroneous use by the caller", while announcing that this behavior "very likely will be changed in the upcoming release cycle".

In practice, the fix to deploy is OpenSSH's. A musl machine whose OpenSSH is not up to date remains exposed, whatever its musl version.

Fixed Alpine packages

Alpine backported the fix to every branch since 3.16, including those no longer maintained (3.16 to 3.20).

Alpine branchFixed openssh package (or later)Point release
edge10.6_p2-r0
3.2410.3_p1-r23.24.4
3.2310.2_p1-r13.23.8
3.2210.0_p1-r113.22.8
3.219.9_p2-r13.21.10
3.209.7_p1-r6Package only, branch out of support
3.199.6_p1-r3Package only, branch out of support
3.189.3_p2-r4Package only, branch out of support
3.179.1_p1-r7Package only, branch out of support
3.169.0_p1-r6Package only, branch out of support

Checking a host

Checks are done locally, as root. We advise against testing a login to judge exposure, and against running the unaudited detection scripts circulating since 5 November (OX Security has warned about them).

C library and installed package

cat /etc/alpine-release                      # Alpine, and which version
ldd /usr/sbin/sshd | grep -i musl            # is sshd linked against musl?
apk info -v 2>/dev/null | grep '^openssh-server'

Then compare the package version with the table above.

Effective sshd configuration

sshd -T | grep -Ei '^(usepam|passwordauthentication|permitrootlogin)'

Two remarks on the output:

  • an sshd built without PAM shows no usepam line, which is expected;
  • sshd -T shows the global configuration, while a Match block can re-enable passwords for a user or a network. Read the file, or test a specific case with sshd -T -C user=alpine,host=example,addr=203.0.113.10.

Affected accounts

awk -F: '$2 == "*" {print "no password:", $1}' /etc/shadow
awk -F: '$2 ~ /^\$[56]\$/ {print "real hash:", $1}' /etc/shadow

The host was exploitable if both lists are non-empty, passwords are enabled and the package is not fixed.

Beyond root, look first at key-only service and deployment accounts, and at the alpine account on cloud images.

Remediation

In order of effectiveness:

  1. Update, then restart sshd. Alpine's advisory points it out: updating the package does not replace the running daemon.
    apk upgrade -U -a
    rc-service sshd restart
  2. Disable password authentication if the update cannot happen right away. First check that key-based login works, and keep a session open while you make the change. Method published by Alpine:
    mkdir -p /etc/ssh/sshd_config.d
    echo 'PasswordAuthentication no' > /etc/ssh/sshd_config.d/00-no-passwords.conf
    sed -i.bak -e '1i PasswordAuthentication no' \
      -e 's/^\(\s*PasswordAuthentication[^y#]*\)yes/\1no/i' \
      /etc/ssh/sshd_config
    sshd -t && rc-service sshd restart
    sshd -T | grep -i passwordauthentication     # should print: passwordauthentication no
    The sshd_config.d directory is only read by default from Alpine 3.19 onward, hence the change to the main file, which also covers Match blocks. The original is kept in sshd_config.bak.
  3. Rebuild images that ship openssh-server (Docker images, VM templates, internal AMIs) from a fixed base. To administer a container, docker exec or kubectl exec avoid running an SSH server in it.
  4. Limit exposure: firewall filtering or VPN access, and removal of the alpine account's passwordless doas where it is not used.

We recommend keeping PasswordAuthentication no once the package is fixed. An SSH server reachable from the Internet rarely needs to accept passwords, and doing without them also rules out brute-force attacks.

One last measure is going around: replacing * with ! in /etc/shadow. It blocks the attack, but without PAM, OpenSSH then treats the account as locked and also refuses key-based login. That is exactly what led Alpine to switch from ! to * in 2022; we reserve it for accounts that are never used to log in.

Looking for compromise

No network indicators have been published. The usable trace is in the authentication logs:

  • on Alpine, /var/log/messages and its rotated files. An sshd line reading "Accepted password for" that names an account without a password (alpine, root, a key-only account) has no legitimate explanation;
  • central log collection, the only source left for containers and instances already destroyed.

If such a line shows up, or if the logs do not allow a conclusion on an exposed host, we would treat the machine as compromised:

  • review of doas usage, recent accounts, modified files and authorized_keys;
  • rebuilding the machine rather than cleaning it;
  • rotation of the secrets it held (keys, tokens, passwords to other systems).

Timeline

OpenSSH was notified on 4 November and released the fix the next day, without the lead time distributions are usually given to prepare.

Damien Miller explained the decision on the OpenSSH developers' list. The team has seen "multiple cases of rapid bug rediscovery by AI agents, sometimes within hours", and now considers "long embargo periods to be a dangerous practice that primarily benefits attackers".

The day before, writing about CVE-2026-98432, we described a remote root exploit written by an AI model in under an hour. Both cases point the same way: the time to prepare between a fix and its possible exploitation is shrinking.

Timeline

CVE-2026-123158 timeline

Origins

  1. August 2012

    musl changes crypt()

    the function returns * on failure; SHA-crypt arrives three weeks later, with a key limited to 256 bytes.

  2. July 2016

    Fix for CVE-2016-6210

    sshd borrows a real salt for accounts without a valid hash.

  3. May 2022

    Alpine 3.16

    root moves from ! to * in base images.

Disclosure

  1. 4 November 2026

    Report to OpenSSH

    across about 17,600 unusual logins, only the musl without PAM combination behaves differently.

  2. 5 November 2026

    OpenSSH 10.6p2 and Alpine advisory

    fixed packages for every branch since 3.16, CVE published by MITRE late in the day.

Aftermath

  1. 6 November 2026

    No exploitation reported

    CISA places exploitation at the proof-of-concept stage, and the flaw is not in the KEV catalog.

The first three dates are the technical choices whose combination produces the flaw.

Detection from the outside

Flawfence does not attempt any authentication against your SSH servers, and such a test would add nothing that the local check does not do better. The flaw is in any case poorly suited to remote detection:

  • the SSH banner gives the OpenSSH version, not the C library or whether PAM is used;
  • fixed Alpine packages keep their upstream version number, so the banner cannot tell a fixed server from a vulnerable one.

Our role comes earlier. Flawfence lists the SSH servers exposed on the Internet in your name, places their observable versions when possible, and flags those that appear or reappear after a migration.

With that list, on the day of an advisory like this one, you know within the hour which machines to check. It is built before the flaw, by mapping your information system and inventorying your external attack surface continuously.

Frequently asked questions about CVE-2026-123158

What is CVE-2026-123158?

A password authentication bypass in sshd, OpenSSH's server, nicknamed "sshole". On Linux with musl and without PAM, an account with no password (* in /etc/shadow) can accept a login with a very long password. It is rated 8.1 under CVSS 3.1 and fixed in OpenSSH 10.6p2.

Is my Debian, Ubuntu or RHEL server affected?

No. These distributions use glibc and PAM, and do not meet the conditions. Red Hat confirms that none of its products are affected. The flaw concerns musl systems, Alpine Linux first among them.

Are my Alpine-based Docker containers vulnerable?

Only if they run an SSH server that accepts passwords, which is rare. In that case, rebuild the image from a fixed base rather than updating the container in place.

Which version fixes the flaw?

OpenSSH 10.6p2 upstream. On Alpine, the fixed openssh package depends on the branch: 10.3_p1-r2 on 3.24, 10.2_p1-r1 on 3.23, 10.0_p1-r11 on 3.22, 9.9_p2-r1 on 3.21, and so on down to 3.16. Restart sshd after the update.

How can I protect a server without updating right away?

By disabling password authentication (PasswordAuthentication no), after checking that key-based login works, then restarting sshd. OpenSSH and musl's maintainer both recommend this measure.

Is the flaw being exploited?

No exploitation had been reported as of 6 November 2026, and the flaw is not in CISA's KEV catalog. Reproduction environments are public, however, and CISA places exploitation at the proof-of-concept stage.

How can I tell whether an attacker has logged in?

Search sshd logs for "Accepted password for" lines naming an account that has no password (alpine, root, key-only accounts). Such a line has no legitimate explanation: the machine should be treated as compromised.

Sources

Let’s discuss your external exposure

Request a personalized Flawfence demo and discover your real exposure level.