On November 5, 2026, the Linux ecosystem disclosed a security vulnerability that subverted conventional cryptographic wisdom. Across millions of Alpine-based containers, administrator accounts configured to prohibit password authentication were compromised. An attacker simply needed to submit a 257-character random string into the password prompt to gain direct administrative privileges.
Common sense dictates that longer passwords offer greater security, and excessively long inputs ought to be rejected by defensive boundaries. Here, reality proved otherwise: a fortified access control perimeter was swung wide open by a string of arbitrary keystrokes.
Breaking Through Defenses: Gaining Access with a 257-Byte Password
The conditions required to trigger this vulnerability are precise yet surprisingly common. The target server must run an OpenSSH daemon linked against the musl C library without PAM enabled. When an attacker supplies a password between 257 and 1024 bytes in length, authentication is granted immediately.
A 257-byte payload far exceeds typical password lengths. Yet this anomalous input pierced through comparison logic, causing the system to treat an unauthenticated, login-disabled account as successfully validated. Security mechanisms failed completely at that critical juncture.
Vulnerable accounts share a distinctive hallmark: in /etc/shadow, their password field contains a single * character. Under UNIX conventions, an asterisk designates an account that never accepts password authentication. Cloud vendor base images and key-only deployment accounts are typically configured this way.
The easiest targets sit directly in the cloud: the default alpine user in official Alpine AWS and Azure images follows this exact pattern, coupled with passwordless doas privileges. Compromising this account yields instant root access.
As long as another account with a valid password hash exists on the system, the exploit succeeds deterministically. OpenSSH borrows that account’s salt to mitigate timing side channels. Multiple defensive configurations converged—only to inadvertently hand out full access.
Three Sound Decisions, Colliding into a Flaw After 46 Years
Examining the historical evolution of UNIX reveals that this backdoor emerged from three independent engineering decisions spanning nearly five decades. Each decision was rational and rigorous when introduced; their eventual confluence, however, proved catastrophic.
The first decision dates back to 1980. Bill Joy inserted an asterisk * into the password field of the daemon service account in 3BSD. At the time, the crypt algorithm could not produce a single asterisk, guaranteeing that no entered password would ever match.
Figure: Screenshot of the original 1980 3BSD passwd file, showing the password field of the daemon account populated with an asterisk. Source: sshhole.com
This convention of locking accounts with an asterisk persisted for 46 years, becoming the universal industry standard for designating non-login accounts.
The second decision arrived in 1997. The Single UNIX Specification mandated that the password encryption function crypt() should return a null pointer upon computation failure. However, many C programs omitted null pointer checks, and dereferencing NULL led to segmentation faults that crashed network services.
In August 2012, the lightweight musl C library addressed this hazard. In commit b3c4cc12, the library modified crypt() to return a single asterisk * on calculation error, explicitly removing code comments asserting that errors were impossible.
Figure: musl header comments explicitly noting that a single asterisk is returned whenever an error occurs during computation. Source: sshhole.com
To musl developers, an asterisk signified computation failure. To system administrators, an asterisk signified disabled login. Two groups assigned entirely divergent semantics to the exact same character.
A DoS Buffer Limit Meets a Timing Side-Channel Defense
The third decision bridged the two asterisks. On August 29, 2012—just twenty days after the previous change—musl introduced SHA-512 password hashing support.
SHA-512 is computationally expensive, and hashing latency scales with input size. To protect servers against denial-of-service exhaustion, musl imposed a strict 256-byte ceiling on input passwords. Inputs exceeding 256 bytes were immediately rejected, returning a single asterisk *.
Figure: musl libc enforcing a 256-byte maximum length in crypt_sha512.c to prevent excessively long inputs from exhausting server resources. Source: sshhole.com
This 256-byte hard cap successfully mitigated resource exhaustion attacks and ran quietly in production for years.
In July 2016, OpenSSH resolved CVE-2016-6210, a timing side-channel vulnerability where responses for non-existent users arrived faster, allowing attackers to enumerate valid usernames. To equalize execution times across all requests, OpenSSH introduced dummy hashing rounds.
When authenticating against an account lacking a password hash, OpenSSH borrowed the salt from an existing valid account and ran a hash iteration purely to consume time. Disabled accounts marked with an asterisk were routed straight through this dummy computation path.
The vulnerability chain was now locked into place. An attacker sends a 257-byte password to the root account. OpenSSH borrows a salt and invokes crypt(). musl sees the length exceeding 256 bytes, aborts calculation, and returns *. OpenSSH compares this returned * against /etc/shadow, finds an exact match, and immediately grants access.
How Containerization Scaled a Niche Artifact to Millions of Cloud Hosts
musl was historically favored in embedded systems such as home routers, where attack surfaces remained minimal. The rise of containerization propelled this lightweight C library directly to the modern server mainstream.
Alpine Linux, weighing in at just 5MB, swiftly became the ubiquitous base image across the global container landscape. In 2019, Alpine patched an issue involving empty root passwords by switching the locked field to an exclamation mark !. However, the exclamation mark broke SSH public key authentication in environments without PAM, disrupting deployments across major cloud providers.
With Alpine 3.16 released in 2022, maintainers reverted root’s password field back to an asterisk *, restoring public key logins. This alteration, however, left all subsequent container images directly exposed to the bypass preconditions.
The tech community quickly evaluated the blast radius. Developer jbyers observed that while the probability of any single container meeting all criteria might seem moderate, multiplying that rate across hundreds of millions of containers worldwide yielded alarming totals. Countless production workloads had inadvertently grounded on this hidden reef.
Debates also erupted over standard compliance. Developer NewJazz questioned whether musl had drifted from POSIX specifications. Others countered with POSIX excerpts, pointing out that the standard specifies only a single error code, leaving error-handling semantics ambiguous at best.
On Lobsters, commenter mort criticized the dramatic disclosure style of security writeups, arguing that vulnerability disclosures should remain direct and prioritize impact scope and remediation steps.
Package Updates Aren’t Enough: Daemons Must Be Restarted
On November 5, 2026, upstream OpenSSH released version 10.6p2. The patch incorporates explicit filtering against single-character return values, preventing the application layer from naively trusting libc error conventions.
Updating packages, however, is only half the battle. Linux process persistence presents a widespread operational blind spot.
While package managers replace binaries on disk, long-running processes resident in memory continue executing legacy code. Unless services are actively restarted, systems remain vulnerable. System administrators must restart sshd or rebuild and redeploy running containers for the fix to take effect.
Reflecting on this vulnerability, not a single line of code was written with malicious intent. In 1980, an asterisk was introduced to disable access; in 1997, return values were specified to avoid crashes. In 2012, length limits defended against denial of service, and in 2016, dummy computations mitigated timing attacks. Every individual decision was sensible and defensible in its historical context.
Yet across four decades, these defensive layers intersected. A subtle semantic discrepancy opened a silent privilege escalation path. In complex software architectures, defensive mechanisms layered atop one another without mutual understanding often harbor risks far more elusive than isolated flaws.
References:
- Original vulnerability disclosure and online test tool at sshhole.com
- Alpine aports commit fbe926af: Switching root password field from exclamation mark to asterisk
- OpenSSH 10.6p2 official release notes and patch source
- Hacker News discussion on musl crypt error return values
- Lobsters discussion on container security boundaries and operational remediation