Securitysshole: password bypass in Alpine’s OpenSSH

sshole (CVE-2026-123158): Alpine OpenSSH password bypass — fixed versions and checker

On Alpine Linux and other musl-based systems where sshd checks passwords without PAM, any password between 256 and 1024 characters logs in to an account that has no password (* in /etc/shadow): key-only users, the alpine user on Alpine’s cloud images, or root where PermitRootLogin is yes. Fixed in OpenSSH 10.6p2 and in Alpine’s openssh packages for 3.16 to edge.

Not in CISA’s Known Exploited Vulnerabilities catalog as of Nov 6, and no attacks have been reported. CISA’s assessment on the CVE record: proof of concept public, not automatable, total technical impact. Several proof-of-concept and scanner repositories appeared on GitHub within a day; don’t run unreviewed ones.

What to do now

  1. Upgrade openssh on every Alpine host: apk upgrade -U -a. Fixed builds: 10.3_p1-r2 (3.24), 10.2_p1-r1 (3.23), 10.0_p1-r11 (3.22), 9.9_p2-r1 (3.21), 10.6_p2-r0 (edge); older branches are in the table below.
  2. Restart sshd (rc-service sshd restart). Upgrading the package alone doesn’t replace the daemon that is already running.
  3. Rebuild every image that installs openssh-server from a freshly pulled Alpine base, and redeploy. An image built before Nov 5 still has the vulnerable package.
  4. If you can’t upgrade today, set PasswordAuthentication no in a file under /etc/ssh/sshd_config.d/ and restart sshd. Check that your key login works before you disconnect.
  5. Look for “Accepted password for” on accounts without a password (root, alpine, key-only users) in /var/log/messages. If you find one, treat the host as compromised.

Fixed openssh-server builds by Alpine branch

The CVE record lists OpenSSH before 10.6p2 on Linux when musl libc is used without PAM. Alpine’s default openssh-server package is built without PAM; openssh-server-pam with UsePAM yes is not affected. glibc distributions such as Debian, Ubuntu, Fedora and RHEL are not affected, and neither are Dropbear or SSH servers written in Go.

Am I exposed to sshole?

The bug needs four things at once. The check walks through each of them, then compares your openssh-server revision with Alpine’s fixed build for your branch: ssh -V can’t show it. Nothing you paste leaves this page.

doas sh <<'EOF'   # or: sudo sh <<'EOF'
cat /etc/alpine-release
apk info -v 2>/dev/null | grep '^openssh-server'
sshd -T 2>/dev/null | grep -Ei '^(usepam|passwordauthentication|permitrootlogin) '
awk -F: '$2=="*"{print "no-password account: "$1} $2~/^\$[56]\$/{n++} END{if(NR) print "password accounts: "n+0}' /etc/shadow
for p in $(pidof sshd); do echo "running sshd: $(readlink /proc/$p/exe)"; done
EOF

Read-only: it prints the Alpine release, the openssh-server package, three sshd settings, the names of accounts without a password and a count of accounts with one. It never prints password hashes.

or try an example:

Who has shipped the fix

ssh -V shows the same upstream version before and after the fix: Alpine changed only the package revision (for example 10.3_p1-r1 → 10.3_p1-r2). Compare the full package version, and check images by their build date, not their tag.

OpenSSH portable

OpenSSH 10.6p2 (Nov 5, 2026) adds a workaround in sshd for systems that use musl libc without PAM. The root cause is in how musl’s crypt() reports errors, so the fix lands in sshd rather than in musl.

  • 10.6p2: openssh-portable 10.6p2

Check: ssh -V # upstream builds only; on a distribution, compare the package revision

Buildroot

Images built with musl and without linux-pam get sshd without PAM and password logins on, so they are affected; glibc is the default toolchain. OpenSSH 10.6p2 is in master only (Nov 5): no tagged release or stable branch has it yet, so rebuild from master or apply the bump yourself.

  • master: openssh 10.6p2

Check: grep -E '^BR2_TOOLCHAIN_USES_MUSL|^BR2_PACKAGE_LINUX_PAM' .config

Yocto Project / OpenEmbedded-Core

Builds with TCLIBC = "musl" and without pam in DISTRO_FEATURES get sshd without PAM and are affected (both are off by default: glibc, no pam). No fix is merged yet; an upgrade to 10.6p2 was posted to the OE-core list on Nov 6. Until then add pam to DISTRO_FEATURES, carry the upstream patch or set PasswordAuthentication no.

Check: bitbake-getvar --value TCLIBC; bitbake-getvar --value DISTRO_FEATURES

alpine (Docker Official Image)

The base image doesn’t include an SSH server. Images that run apk add openssh-server keep the package that was current when they were built: rebuild them from a freshly pulled base (alpine:3.24 is now 3.24.4) and redeploy.

Check: docker run --rm <your-image> apk info -v openssh-server

linuxserver/openssh-server

Tag 10.3_p1-r2-ls242 (latest, built Nov 5) ships the fixed openssh-server-pam 10.3_p1-r2. The image runs the PAM build with UsePAM left at no, so PAM doesn’t protect older tags; password logins are off unless PASSWORD_ACCESS=true. Pull the new tag and recreate the container.

  • tag 10.3_p1-r2-ls242: openssh-server-pam 10.3_p1-r2

Check: docker exec <container> apk info -v openssh-server-pam

atmoz/sftp (alpine tag)

The alpine tag was rebuilt on Nov 5 with openssh-server-pam 10.3_p1-r2 (fixed). Older alpine builds were exposed in the documented setup: password logins on, UsePAM at no, key-only users (foo::1001) stored as *, and any user with a password gives the hash the bug needs. Re-pull atmoz/sftp:alpine and recreate containers. The latest and debian tags are Debian and not affected.

  • tag alpine (build of Nov 5): openssh-server-pam 10.3_p1-r2

Check: docker exec <container> apk info -v openssh-server-pam

gitea/gitea (rootful)

latest (28.3.0, built Nov 1) still ships the vulnerable openssh-server 10.3_p1-r1, but the sshd_config written at every start sets PasswordAuthentication no, and the image has no account with a password. The 28-nightly build of Nov 6 already has 10.3_p1-r2; update when the next release ships.

Check: docker exec <container> apk info -v openssh-server

gitea/gitea (-rootless tags)

No OpenSSH server in the image: SSH is served by Gitea’s built-in Go server.

Check: docker exec <container> sh -c 'apk info -e openssh-server || echo not installed'

codeberg.org/forgejo/forgejo (rootful)

Tag 17 (17.0.1) ships the vulnerable openssh-server 10.3_p1-r1 and LTS tag 15 (15.0.11) ships 10.2_p1-r0, but the sshd_config written at start sets PasswordAuthentication no, and the image has no account with a password. Update to the next point release when it ships.

Check: docker exec <container> sh -c 'cat /etc/alpine-release; apk info -v openssh-server'

codeberg.org/forgejo/forgejo (-rootless tags)

No OpenSSH server in the image: SSH is served by Forgejo’s built-in Go server.

Check: docker exec <container> sh -c 'apk info -e openssh-server || echo not installed'

gogs/gogs

latest (0.14.3, built in June) ships openssh-server 9.9_p2-r0 on Alpine 3.21, below the fixed 9.9_p2-r1, but sshd runs with Gogs’ own sshd_config, which sets PasswordAuthentication no, and the image has no account with a password. Update when a rebuilt tag ships.

Check: docker exec <container> apk info -v openssh-server

jenkins/ssh-agent (alpine tags)

The alpine tags (release 9.3.3, built Oct 30) ship the vulnerable openssh-server 10.3_p1-r1, but the image’s sshd_config sets PasswordAuthentication no and the entrypoint doesn’t change it. Update to the next release. The default latest and jdk tags are Debian and not affected.

Check: docker exec <container> apk info -v openssh-server

panubo/sshd (quay.io)

quay.io/panubo/sshd:latest (1.10.0) ships openssh-server 10.0_p1-r10, below the fixed 10.0_p1-r11; the stale Docker Hub image (2023, Alpine 3.14) gets no fix at all. Password logins are off unless SSH_ENABLE_PASSWORD_AUTH or SSH_ENABLE_ROOT_PASSWORD_AUTH is true; with either one on, rebuild with apk upgrade or wait for a new tag.

Check: docker exec <container> sh -c 'cat /etc/alpine-release; apk info -v openssh-server'

hermsi/alpine-sshd

latest (10.3_p1-r1-alpine3.24, built Sep 21) ships the vulnerable openssh-server 10.3_p1-r1 with password logins at the OpenSSH default (on). In the documented setups root is refused or gets a password and SSH_USERS get an empty password field rather than *, so a default container has no account the bug can use; any * user you add yourself is exposed. Rebuild with apk upgrade or set PasswordAuthentication no.

Check: docker exec <container> apk info -v openssh-server

binlab/bastion

latest (2020) runs openssh-server 8.1_p1-r0 on the end-of-life Alpine 3.11, which gets no fix, but the entrypoint always starts sshd with PasswordAuthentication=no. The project is no longer updated; move to a maintained image.

Check: docker exec <container> sh -c 'cat /etc/alpine-release; apk info -v openssh-server'

sickp/alpine-sshd

Archived since 2019: Alpine 3.9 with openssh-server 7.9_p1-r5, a branch with no fixed package. It has no * account by default, but password logins and root login are on with the documented password root, so it is unsafe on any network regardless of this bug. Replace it.

Check: docker exec <container> sh -c 'cat /etc/alpine-release; apk info -v openssh-server'

instrumentisto/rsync-ssh

Only the OpenSSH client is installed; there is no sshd to log in to.

Check: docker exec <container> sh -c 'apk info -e openssh-server || echo not installed'

drakkan/sftpgo

SFTPGo serves SFTP and SSH from its own Go implementation; neither the Debian nor the alpine image contains an OpenSSH server.

Check: docker exec <container> sh -c 'command -v sshd || echo no sshd'

Alpine Linux

Every branch from 3.16 to edge has a fixed openssh build, including the end-of-life 3.16–3.20. Point releases 3.21.10, 3.22.8, 3.23.8 and 3.24.4 include it. Upgrade, then restart sshd: the running daemon keeps the old code. Alpine 3.15 and older get no fix.

  • edge: openssh-server 10.6_p2-r0
  • Alpine 3.24: openssh-server 10.3_p1-r2
  • Alpine 3.23: openssh-server 10.2_p1-r1
  • Alpine 3.22: openssh-server 10.0_p1-r11
  • Alpine 3.21: openssh-server 9.9_p2-r1
  • Alpine 3.20: openssh-server 9.7_p1-r6
  • Alpine 3.19: openssh-server 9.6_p1-r3
  • Alpine 3.18: openssh-server 9.3_p2-r4
  • Alpine 3.17: openssh-server 9.1_p1-r7
  • Alpine 3.16: openssh-server 9.0_p1-r6

Check: apk info -v openssh-server openssh-server-pam

postmarketOS (now Nura)

Not exposed by default: the base package installs Alpine’s openssh-server-pam and sets UsePAM yes. Setting UsePAM no or switching to the non-PAM package would expose it. Alpine’s fixed packages arrive through apk upgrade; restart sshd afterwards.

  • v26.06 (Alpine 3.24): openssh-server-pam 10.3_p1-r2
  • edge: openssh-server-pam 10.6_p2-r0

Check: apk info -v openssh-server-pam; sshd -T | grep -i '^usepam'

OpenWrt

The default SSH server, Dropbear, is not affected. The optional openssh-server package is built without PAM with password logins on, so it is affected; openssh-server-pam turns PAM on and passwords off. Fixed builds are rolling out per architecture: upgrade once your target shows the new version, then restart sshd.

  • 25.12: openssh-server 10.6_p2-r1
  • 24.10: openssh-server 9.9_p2-r2

Check: apk list -I 'openssh-server*' 2>/dev/null || opkg list-installed 'openssh-server*'

Void Linux (musl)

Void builds openssh with PAM and ships UsePAM yes, so default installs were not exposed. openssh 10.6p2_1 is in all musl repositories since Nov 5; xbps-install -Su restarts a running sshd.

  • current (musl): openssh 10.6p2_1

Check: xbps-query -p pkgver openssh

Chimera Linux

Chimera builds openssh with PAM and makes UsePAM default to yes, so default installs were not exposed. openssh 10.6_p2-r0 has been in the repository since Nov 5: apk upgrade, then restart sshd.

  • current: openssh 10.6_p2-r0

Check: apk list -I openssh

Gentoo Linux (musl profiles)

Default musl profiles use PAM (with PasswordAuthentication no) and libxcrypt, so default installs are not exposed; only USE=-pam systems are. net-misc/openssh-10.6_p2 is stable on amd64, x86 and ppc64; arm, arm64 and ppc are still being stabilized.

  • stable amd64, x86, ppc64: net-misc/openssh 10.6_p2

Check: portageq best_version / net-misc/openssh

Adélie Linux

openssh 9.9_p2-r1 has no fix yet and checks passwords without PAM (UsePAM stays no), but default accounts are locked with ! rather than *, so a default system has no account the bug can use. Any account set to * (usermod -p '*') is exposed: set PasswordAuthentication no until a fix ships.

Check: awk -F: '$2=="*"{print $1}' /etc/shadow

Red Hat (RHEL, OpenShift)

Red Hat states its products are not affected: RHEL and all Red Hat builds link OpenSSH against glibc and use PAM.

Amazon Linux

Amazon lists openssh as not affected on Amazon Linux 2, Amazon Linux 2023 and the Amazon Linux 2027 preview.

Alpine official cloud images (AWS, Azure, GCP, OCI, NoCloud)

Tiny-cloud images 3.18.11 through 3.24.3 ship an alpine user with a * password field and passwordless doas; cloud-init images write PasswordAuthentication no and are not affected. Fixed images 3.24.4, 3.23.8, 3.22.8 and 3.21.10 (with new AWS AMIs) were published on Nov 5. New images only help new instances: update openssh on every running instance and restart sshd.

  • 3.24.4: openssh 10.3_p1-r2
  • 3.23.8: openssh 10.2_p1-r1
  • 3.22.8: openssh 10.0_p1-r11
  • 3.21.10: openssh 9.9_p2-r1

Check: apk info -v openssh-server; awk -F: '$2=="*"{print $1}' /etc/shadow

Akamai Cloud (Linode) Alpine images

Linode’s stock Alpine 3.21–3.24 images were last updated on Oct 30, before the fix. Akamai hasn’t published their sshd or account setup, so exposure is unknown: run apk upgrade and restart sshd on existing and new Alpine Linodes.

Check: apk info -v openssh-server

Interim mitigations

FAQ

What is sshole?

sshole is the nickname of CVE-2026-123158, a password authentication bypass in OpenSSH’s sshd on Linux systems that use musl libc without PAM, such as Alpine Linux. When a password is longer than 256 bytes, musl’s crypt() returns "*" as an error value. sshd compared that with the stored password field, and accounts with no password store exactly "*", so the comparison matched and the login succeeded.

Is my Alpine server vulnerable?

Only if four things are true at once: sshd checks passwords without PAM (Alpine’s default openssh-server package), password logins are on (the OpenSSH default), an account that may log in has * as its password field (a key-only user, the alpine user on cloud images, or root with PermitRootLogin yes; the default refuses root passwords), and at least one other account has a password. The check on this page walks through each condition.

Why doesn’t ssh -V tell me whether I’m patched?

Alpine fixed older branches by adding OpenSSH’s workaround to the version they already ship, so only the package revision changed (for example 10.3_p1-r1 to 10.3_p1-r2 on Alpine 3.24). Run apk info -v openssh-server and compare the full version with the table above.

Are Debian, Ubuntu or RHEL affected?

No. They use glibc and build sshd with PAM, and the bug needs musl libc without PAM. Containers based on Debian, Ubuntu or distroless images are not affected either.

Are Docker containers affected?

Only containers that run an OpenSSH server on Alpine (or another musl image without PAM) with password logins enabled. Gitea, Forgejo, Gogs and the Jenkins SSH agent turn password logins off; atmoz/sftp:alpine builds from before Nov 5 were exposed in their documented setup with key-only users. The container rows above have image-by-image status. Containers that don’t run sshd are not affected, and images built before Nov 5, 2026 keep the vulnerable package until you rebuild them.

Do I need to restart sshd after upgrading?

Yes. Alpine’s advisory says upgrading the package doesn’t replace the daemon that is already running. Run rc-service sshd restart, or restart the container.

Is sshole exploited in the wild?

As of Nov 6, 2026, no attacks have been reported and the CVE is not in CISA’s Known Exploited Vulnerabilities catalog. Proof-of-concept code is public, so treat any exposed, unpatched host as at risk.

How do I check whether someone already logged in?

Search /var/log/messages (or your log collector) for sshd “Accepted password for” lines on accounts that have no password, such as root, alpine or key-only users. Also review recently created users and files, authorized_keys and doas or sudo use. If you can’t rule out a login, treat the host as compromised.

Use this tracker in your tooling

The vendor table is available as JSON (CC BY 4.0). Use it in scripts, dashboards or CI checks.

curl https://www.changes.watch/api/v1/advisories/sshole

Sources

Found an outdated status? Tell us via contact — every row links to the vendor's own advisory.