Skip to content
SSH Authentication Bypass on Alpine Linux: 257-Byte Password Authenticates as Root via musl crypt() Bug Decryption Digest - Cybersecurity Threat Intelligence / 52min A bug in musl libc's crypt() function lets any password of 257 bytes or longer authenticate as root, or as any user whose account is configured to accept only SSH keys, on Alpine Linux 3.16 and later. 257 — bytes is the minimum password length needed to trigger the musl crypt() failure that returns * and matches a locked account's s

SSH Authentication Bypass on Alpine Linux: 257-Byte Password Authenticates as Root via musl crypt() Bug Decryption Digest - Cybersecurity Threat Intelligence / 52min A bug in musl libc's crypt() function lets any password of 257 bytes or longer authenticate as root, or as any user whose account is configured to accept only SSH keys, on Alpine Linux 3.16 and later. 257 — bytes is the minimum password length needed to trigger the musl crypt() failure that returns * and matches a locked account's s

www.decryptiondigest.com • November 6, 2026

Sponsor a slot and put your brand in front of CISOs, engineers, and IT decision-makers.

Most urgent if: you run Alpine Linux instances or containers with SSH password authentication enabled, or you deploy OpenWRT, Buildroot, or Yocto systems accessible over SSH. If you use glibc-based Linux distributions (Debian, Ubuntu, RHEL, Amazon Linux 2), enforce key-only SSH authentication globally, or have already deployed OpenSSH 10.6p2, your exposure is minimal.

A bug in musl libc's crypt() function lets any password of 257 bytes or longer authenticate as root, or as any user whose account is configured to accept only SSH keys, on Alpine Linux 3.16 and later. No credentials are required: a string of 257 'A' characters suffices. The same bug affects OpenWRT, Buildroot, Yocto, and any other musl-based Linux system where SSH password authentication is not explicitly disabled.

The root cause is a collision between two independent design decisions made twelve years apart. In 2012, musl's sha512crypt implementation added a 256-byte limit on password length to prevent denial-of-service. When the limit is exceeded, crypt() returns the string * to signal failure. In 2022, Alpine Linux solved a separate problem: prior lockout methods for the root account also disabled SSH key authentication. The fix was to store * in root's shadow hash field, which blocks password logins while allowing keys. The collision: * == * means any oversized password authenticates as any *-locked account.

The fix is in OpenSSH 10.6p2, released in early November 2026. Alpine Linux has shipped the fix via apk. The vulnerability is tracked as CVE-2026-123158 and public proof-of-concept code is available on GitHub.

How the Bug Works: crypt() Returns What Shadow Stores

The authentication bypass follows directly from two decisions that were each individually sound.

musl crypt() and the 256-byte limit. musl libc's sha512crypt implementation caps password input at 256 bytes (#define KEY_MAX 256). The cap exists to bound CPU time, since sha512crypt is intentionally compute-heavy and an unbounded password would allow a denial-of-service attack. When a password exceeds 256 bytes, the function fails and returns *, a string that cannot be a valid sha512crypt hash output, so it is safe to compare against stored hashes -- it should never match anything.

Alpine 3.16 and the locked-but-key-capable account. In 2019, Alpine Docker images were found to have no root password at all (CVE-2019-5021): root's shadow hash was empty, so any password worked. Alpine locked root by setting its shadow hash to !. This blocked password logins, but also broke SSH key authentication on systems without PAM. In 2022, Alpine 3.16 changed root's shadow hash to *, which maintains the locked state while keeping SSH keys functional on PAM-disabled systems. The rationale was correct: * is not a valid hash, so no password should ever produce it.

The collision. When sshd authenticates a user against a * shadow hash, it calls crypt(password, " "). A 257-byte or longer password causes sha512crypt to hit KEY_MAX, triggering the error path, which returns . The result: crypt("AAAAAA...257+", " ") == " ". sshd compares this to the stored shadow hash "*". Match. Authentication granted.

Blast radius: Sending a 257-byte password over SSH gives an unauthenticated attacker full access to any account whose shadow hash is * on Alpine Linux 3.16 or later running musl libc with password authentication enabled. On official Alpine AWS and Azure images, this includes unauthenticated root access with no prior credentials, no interaction, and no prior access to the system.

The attack requires password authentication to be enabled in sshd_config. Alpine's default configuration has PasswordAuthentication set to yes. Cloud images commonly override this to key-only, but not universally.

Why only 257-1024 bytes? The KEY_MAX cap is 256 bytes; passwords exactly 256 bytes or shorter are hashed normally. Passwords over 1024 bytes are rejected by sshd before reaching crypt(). The exploitable window is 257-1024 bytes, any character composition.

Identify Vulnerable SSH Host

Attacker identifies an Alpine Linux, OpenWRT, or other musl-based host with SSH port open and password authentication enabled. Any account with * as its /etc/shadow hash is a valid target, including root on Alpine 3.16+.

Submit 257-Byte Password to sshd

Attacker sends a password between 257 and 1024 bytes in length over SSH. No prior knowledge of any real password is needed. The content is irrelevant; only the length matters. ssh root@target sends the oversized string.

crypt() Returns * Matching Stored Hash

sshd calls crypt(oversized_password, "*"). musl sha512crypt exceeds KEY_MAX 256, fails, and returns "*". sshd compares this to the stored shadow hash "*". Match: authentication succeeds and sshd logs a successful password login.

Obtain Interactive Shell

On Alpine official cloud images, root's shadow hash is * and root has passwordless doas access. Attacker receives a root shell. The auth.log shows "Accepted password for root" with no sign of compromise beyond the successful login.

Detection and Indicators

The attack leaves a clear trace in sshd authentication logs, though it looks like a successful password login rather than an intrusion. The key signal is password authentication succeeding for an account that should only accept keys.

Primary detection opportunity: Any sshd log entry showing "Accepted password for root" on Alpine Linux 3.16+ should be treated as an incident. Root's shadow hash is * on these systems; no legitimate password authentication should ever succeed.

Secondary indicator: Authentication attempts with unusual password lengths. While most sshd logs do not record password length, some security tooling and SIEM integrations capture authentication metadata that can surface anomalous input sizes.

Configuration audit: The most reliable preventive check is auditing /etc/shadow for any user account with * as its hash value and confirming that PasswordAuthentication is disabled for those accounts or globally in sshd_config.

Automated: deploy to your SIEM/EDR to alert continuously when this behavior occurs.

SSH Password Authentication Success for Root Account

Detects successful SSH password authentication for the root account, which should never occur on Alpine Linux 3.16+ where root shadow hash is *. Any match indicates exploitation of the musl crypt() authentication bypass or an unexpected configuration.

SSH Password Auth Success on musl Linux (sshhole bypass pattern)

Detects successful SSH password authentication on systems using musl libc. Tune to known-key-only accounts identified from /etc/shadow audit. Any successful password auth for a * account indicates exploitation.

Manual: run on-demand to historical logs for evidence of past exploitation.

14-Day Hunt: SSH Password Auth Success on musl Linux (sshhole bypass)

Retrospective hunt for SSH password authentication successes that may indicate exploitation of the musl crypt() authentication bypass.

Briefings like this, every morning before 9am.

Immediate Remediation Steps

The fix is in OpenSSH 10.6p2, available now for Alpine Linux via apk. If you cannot patch immediately, disabling password authentication in sshd eliminates the attack surface entirely with a one-line configuration change that takes effect after a service restart.

Patch OpenSSH on all Alpine Linux hosts

apk upgrade openssh, then rc-service sshd restart. Verify the installed version is 10.6p2 or later: ssh -V.

If patching is not possible today, disable password authentication now

echo 'PasswordAuthentication no' > /etc/ssh/sshd_config.d/00-no-passwords.conf && rc-service sshd restart. Verify with: sshd -T | grep passwordauthentication -- output should read passwordauthentication no. This eliminates the attack surface without a package update.

Audit /etc/shadow for all accounts with * as their hash

awk -F: '$2 == "*" {print $1}' /etc/shadow. Any account listed is a potential target if PasswordAuthentication is enabled. Confirm each is intentional and add the PasswordAuthentication no mitigation above.

Set key-only authentication as your standing sshd policy

Add PasswordAuthentication no and ChallengeResponseAuthentication no to /etc/ssh/sshd_config. This should be the default on any externally accessible SSH host regardless of this vulnerability.

Audit container base images for Alpine version

Any Dockerfile or container image using Alpine 3.16 or later as its base may be vulnerable if sshd is installed and password authentication is not explicitly disabled. Audit base image versions and rebuild with patched openssh packages.

History: Seven Decisions That Converged

The researcher who disclosed this at sshhole.com traced the bug through seven distinct changes across Unix, musl, OpenSSH, and Alpine Linux spanning 1980 to 2026.

1980 (3BSD /etc/passwd): Bill Joy introduced * in /etc/passwd for the daemon account. No password could ever hash to *, so it served as a permanent lock marker. The commit message noted the account real name as "The devil himself."

2012 (musl crypt()): musl's crypt() implementation was changed to return * instead of NULL on failure, to avoid segfaults in programs that did not check for NULL before comparing. The commit: "make crypt return an unmatchable hash rather than NULL on failure." A correct assumption -- until * started appearing in shadow files as a lock value.

2012 (musl sha512crypt): Three weeks later, musl added sha512crypt with the KEY_MAX 256-byte cap for DoS protection — the same mechanism that creates the vulnerable code path described in the technical section above. The in crypt_sha512.c explicitly says "on error * is returned." The whole mechanism was documented from day one.

2016 (CVE-2016-6210 timing fix): OpenSSH fixed a timing side channel that let attackers determine whether a username was valid by measuring how long authentication took. For accounts with no real hash, sshd now performs a fake hash using another account's salt to consume equivalent time. For accounts with * as their hash, sshd ends up passing * as the salt to crypt().

2019 (CVE-2019-5021): Alpine Docker images were found to have no root password at all: root's shadow hash was empty. Any password authenticated as root. Alpine locked root by setting its shadow hash to !, blocking password logins. SSH keys stopped working on PAM-disabled systems as a side effect.

2022 (Alpine 3.16): Alpine changed root's shadow hash from ! to *. The rationale: * still blocks password logins while restoring SSH key authentication on PAM-disabled systems. This introduced the vulnerable state: a * hash on a real system, with crypt() returning * on oversized inputs.

2026 (disclosure and fix): A researcher testing sshd builds with musl noticed approximately 17,600 "weird logins" across 12 test builds and traced the cause. OpenSSH 10.6p2 ships with a fix to sshd's pick_salt() function that prevents the * collision path.

None of these decisions were individually wrong. The bug is the product of their combination, undiscovered for ten years.

The musl crypt() bug demonstrates how design decisions made in isolation converge into a critical vulnerability over time. musl returned * to avoid segfaults. Alpine used * to allow SSH keys without PAM. Neither decision was wrong. Combined with OpenSSH's CVE-2016-6210 timing fix and a 256-byte sha512crypt cap, they produced a path where any 257-byte string authenticates as root on every official Alpine Linux AWS and Azure image. The fix is a one-line sshd_config change away. Apply it now: echo 'PasswordAuthentication no' > /etc/ssh/sshd_config.d/00-no-passwords.conf && rc-service sshd restart.

This analysis is generic. create a free account to score threats like this against your own stack .

Frequently asked questions

What is the musl crypt() SSH authentication bypass?

musl libc's crypt() function returns the string * whenever it cannot hash a password, including when the password exceeds 256 bytes. Alpine Linux 3.16 and later store * as the shadow hash for accounts that are locked but should still accept SSH keys. When sshd calls crypt() with a 257-byte or longer password against one of these accounts, crypt() returns * and sshd compares it to the stored * hash. The comparison matches, granting access without any real credentials.

Does this affect my Debian, Ubuntu, or RHEL servers?

No. The bug is specific to musl libc. Debian, Ubuntu, RHEL, Amazon Linux 2, and other glibc-based distributions use glibc's crypt() implementation, which does not return * on failure. glibc returns *0 or *1, which never match the * shadow hash. Only systems using musl libc -- primarily Alpine Linux, OpenWRT, Buildroot, and Yocto -- are affected.

Is there a CVE for this vulnerability?

Yes. The authentication bypass is tracked as CVE-2026-123158. The 2016 OpenSSH timing fix that set up the vulnerable code path is CVE-2016-6210, and the original Alpine empty root password issue is CVE-2019-5021. Public proof-of-concept code for CVE-2026-123158 is available on GitHub.

My Alpine Linux instance is key-only. Am I safe?

Yes, if PasswordAuthentication is set to no in your sshd_config, the attack has no path. The bypass requires sshd to invoke crypt() on the attacker's input. With password authentication disabled, sshd never calls crypt() and the vulnerability cannot be exercised. Confirm with: sshd -T | grep passwordauthentication -- the output should show passwordauthentication no.

Does this only affect root?

No. Any account whose shadow hash is * is vulnerable when password authentication is enabled. On Alpine 3.16+, root's hash is * by default, making it the most prominent target. But any service account, deploy user, or LDAP-mapped user with * stored as its shadow hash is equally vulnerable. Audit with: awk -F: '$2 == "*" {print $1}' /etc/shadow to see which accounts on your system are at risk.

What does OpenSSH 10.6p2 change to fix this?

OpenSSH 10.6p2 modifies the pick_salt() function in sshd's password authentication path. The fix ensures that when sshd selects a fake salt for timing purposes for accounts with * or ! shadow hashes, it uses a randomly generated valid salt rather than the stored * or ! value. This prevents the oversized password from producing an error return value that matches the stored hash.

sshhole.com -- The musl crypt() SSH Authentication Bypass (Researcher Disclosure)

OpenSSH 10.6p2 Release Notes

musl libc: crypt_sha512.c -- KEY_MAX 256 byte cap and * error return

musl commit b3c4cc12: make crypt return * instead of NULL on failure (Aug 2012)

Alpine Linux aports commit fbe926af: switch root hash to * for Alpine 3.16

CVE-2019-5021: Alpine Docker default root password vulnerability

GitHub: SkrudjReal/sshhole-exploit -- CVE-2026-123158 PoC and exploit

GitHub: predkambrij/sshhole-repro -- Docker-based reproduction

Critical CVE Reference Card 2025–2026

25 actively exploited vulnerabilities with CVSS scores, exploit status, and patch availability. Print it, pin it, it with your SOC team.

Ransomware Incident Response Playbook

Step-by-step 24-hour IR checklist covering detection, containment, eradication, and recovery. Built for SOC teams, IR leads, and CISOs.

Daily briefings + Google Top Stories in one step.

Founder & Cybersecurity Evangelist, Decryption Digest

Cybersecurity professional with expertise in threat intelligence, vulnerability research, and enterprise security. Covers zero-days, ransomware, and nation-state operations for 50,000+ security professionals every morning.

Extracted Entities