The Twenty-Five-Seventh Byte: A 14-Year-Old SSH Bug Let Anyone Log Into Password-Less Alpine Servers — and AI Agent Swarms Found It
The Twenty-Five-Seventh Byte: A 14-Year-Old SSH Bug Let Anyone Log Into Password-Less Alpine Servers — and AI Agent Swarms Found It
Published: November 6, 2026 | Reading Time: ~12 minutes | Channel: techminute
In 1980, Bill Joy typed a single character into a file to mean "no one may ever log in as this account." Forty-six years later, that same character — a plain asterisk — became the one thing an attacker needed, along with a password at least 257 bytes long, to walk into servers running one of the most widely deployed operating systems on Earth. No guessing. No retries. One connection, and it works every time.
On November 5, 2026, the OpenSSH project shipped version 10.6p2 with what its own release notes call a "critical security workaround": a password-authentication bypass that affects Linux systems built on the musl libc with PAM disabled — which is the default configuration of Alpine Linux, the base image underneath a very large fraction of the world's containers and cloud instances. Alpine published a security advisory the same day, with fixed packages pushed to every supported release and to branches that stopped receiving regular support years ago, all the way back to 3.16.
The bug is now famous on Hacker News under the finder's chosen name: sshole — 2,823 points and 688 comments as of this writing, sitting at the top of the front page. But the story is far bigger than a rude pun. It is a 14-year chain of four reasonable decisions, made by four different projects, that quietly composed themselves into a master key. It is a lesson about the code nobody reads — the "boring glue" between an SSH daemon and the C library beneath it. And, most remarkably, it is a story about how the bug was found: not by a lone genius with a hex editor, but by an engineer who pointed swarms of AI agents at the problem and threw roughly 17,600 deliberately weird login attempts at every possible build of sshd.
Let's take it apart.
The Context: Four Decisions, One Master Key
The vulnerability has no single author. The disclosure site — built by the finder, Özgün Kültekin of Wakefield (wakefield.co) — reads like an archaeology dig, and every artifact checks out against the primary repos. Here's the chain:
1980 — The asterisk is born. In early Unix, password hashes sat in the world-readable /etc/passwd. For the daemon account, Bill Joy put a * in the hash field. Since a * isn't the output any hashing function can produce, no password can ever match it. Unix has kept this convention for 46 years: * in the password field means "no password login possible" — the standard way to create a key-only account.
1990s — How sshd checks a password. Modern systems keep hashes in /etc/shadow ($6$salt$hash... for SHA-512). sshd hashes your typed password with the stored salt and compares. For an account whose field is *, there's nothing to match — anything you type fails. That's the contract.
2012 — musl breaks the NULL contract. The Single Unix Specification says that when crypt() cannot do its job — say, the requested algorithm doesn't exist — it returns NULL. But plenty of programs never check for NULL and crash on it. So musl, the minimalist C library under Alpine, made a pragmatic call in August 2012: crypt() would stop returning NULL and instead return a single unmatchable character. The character they picked? You guessed it: *. Then, three weeks later (August 29, 2012), musl added SHA-512 crypt — and capped input passwords at 256 bytes to prevent denial-of-service via absurdly long inputs. When crypt() fails on that length check... it returns *. It's in the code comment. It has been there the whole time.
2016 — sshd starts borrowing salt. CVE-2016-6210 was a username-enumeration flaw: asking sshd to authenticate a nonexistent user returned faster than a real one, because there was no hash to compute. OpenSSH's fix was elegant: for accounts with no usable hash, borrow another account's salt and hash the submitted password anyway, burning the same time before saying no. A slower no, but a constant-time no. Crucially, this also covers real accounts whose field is * — there's no salt to borrow from a *, so sshd fetches one from a neighbor.
2022 — Alpine's root becomes a *. In 2019, Alpine had its own scare: CVE-2019-5021, Docker images shipping root with no password at all. The fix locked root with !. But without PAM, ! also killed SSH key logins, which cloud images depend on. So in Alpine 3.16 (2022), root's field became * — locked against passwords, friendly to keys. The aports commit is fbe926af. "Narrator: it did not" fix things, as the disclosure puts it.
Now stack the layers. On a musl system without PAM:
- An account's field is
*(key-only user, LDAP user with no shadow entry, or root on modern Alpine). - Another account on the box has a real
$5$or$6$hash — so sshd has salt to borrow. - You submit a password of 257 to 1,024 bytes.
- sshd borrows the neighbor's salt and calls
crypt(). musl sees the over-limit input, fails, and returns*. - sshd compares the "hash" to the stored field. Both are
*. Match. Come on in.
The 1,024-byte upper bound is sshd's own password-length limit. So the attacker's entire toolkit is: the name of a password-less account, and a password consisting of 257+ bytes of whatever they like. Alpine's advisory is blunt about reliability: "It takes one connection, works every time, and needs no retries."

Under the Hood: Why Nobody Saw It for a Decade
A bug this absurd invites an obvious question: how does something this simple survive ten years in the software that guards half the world's servers?
The answer is a Venn diagram of near-misses:
- The affected path is rare. sshd only hits this code when built without PAM and run on musl. Debian, Ubuntu, Fedora and friends use glibc and PAM — two separate layers of immunity (glibc's libxcrypt returns
*0on failure, one character off from disaster, and PAM never even callscrypt()for a*account). Dropbear and OpenBSD's own SSH are unaffected. The OpenSSH team tests on OpenBSD and glibc systems; musl wasn't in the matrix. - Alpine's default server is exactly the wrong build. Alpine's
openssh-serverpackage is built without PAM, andPasswordAuthenticationis on by default. The officialopenssh-server-pampackage withUsePAM yesis safe — but that's not what most images ship. - The trigger needs two conditions at once. A
*account alone isn't enough; a box where nobody has a password is safe (nothing to borrow). The bug needs the*account and at least one other account with a$5$/$6$hash. Fresh boxes with no passwords set are fine — something has to be set up first, or an admin has to set one password somewhere, before the box turns vulnerable. - The near-misses are painful. In 2013, a Debian developer asked glibc to copy musl's
*sentinel; the thread sits in the libc-alpha archive. Six years later Debian moved to libxcrypt — which chose*0. One character away from arming the same landmine. In December 2024, a musl mailing-list thread discussed busybox'spasswdbreaking on a 257-character password — the exact same*, the exact same limit — and nobody in the thread said "sshd." And in a detail the disclosure clearly savors, an OpenSSH security review on October 30, 2026 fixedpick_salt()— the function that borrows the salt — while the exploitable comparison sat four lines below it. Four days before Kültekin found it.
Even the finder's write-up is honest about the epistemics: "as far as anyone knows, nobody noticed. as far as anyone knows." People may have pasted garbage into password prompts — half a Slack message, a whole SSH key — and been logged in without understanding what happened. That's the quiet horror of a bug that produces a normal-looking success rather than a crash.
Who's actually exposed? Alpine's advisory gives four conditions (all must be true): Alpine's no-PAM openssh-server (or openssh-server-pam with UsePAM no); PasswordAuthentication yes (the default); an account with * in its field; and at least one local account with a $5$/$6$ hash. The * accounts on Alpine include key-only users, directory-service users via musl-nscd, root (which has shipped as root:* since about 3.16), and — most interesting commercially — the alpine user in the official tiny-cloud images (qcow2/VHD/AMI artifacts from 3.18.11 through 3.24.3), which come with passwordless doas. Those images are safe on first boot and become exploitable the moment any $6$ hash exists on the machine — say, when an admin sets a console password or user-data provisions a user with hashed_passwd. At that point an attacker logs in as alpine and doas-es to root. Direct root login stays protected by the default PermitRootLogin prohibit-password — but that doesn't matter if an exposed account can escalate.
Not affected: containers that don't run sshd, systems with PasswordAuthentication no, cloud-init-configured images (which write exactly that), accounts locked with !, machines with no $-style hashes anywhere, and everything on glibc or PAM. Musl-based systems beyond Alpine — OpenWrt, Buildroot, Yocto — are the other places to check, though OpenWrt ships Dropbear by default (not affected) and only matters where an admin has installed OpenSSH.
By the Numbers: The Anatomy of a 10.6p2
| Parameter | Value | Source |
|---|---|---|
| Vulnerable password length | 257–1,024 bytes | Alpine advisory |
| musl crypt() input cap | 256 bytes → returns * |
musl commit 88bf5a8a, Aug 29 2012 |
* sentinel introduced |
Aug 2012 (replacing NULL) |
musl commit b3c4cc12 |
| Salt-borrowing shipped | July 15, 2016 (CVE-2016-6210 fix) | OpenSSH commits list |
Alpine root → * |
3.16, 2022 (commit fbe926af) |
Alpine aports |
| Releases affected | every Alpine release checked: 3.16 → 3.24 + edge | Alpine advisory |
| Fixed point releases | 3.21.10 / 3.22.8 / 3.23.8 / 3.24.4 | Alpine advisory |
| Edge fixed package | 10.6_p2-r0 | Alpine advisory |
| Discovery test volume | ~17,600 adversarial logins across every build | sshhole.com |
| HN traction (at publish) | 2,823 points / 688 comments | HN Algolia |
| CVSS v3.1 | 8.1 High (vendor-assigned; see caveat) | OX Security |
| Known exploitation at disclosure | None reported | Damien Miller via The Hacker News |
The fix itself is characteristically minimal. OpenSSH 10.6p2 makes sshd refuse a match when the stored password field is shorter than four characters — a * (or anything hash-shaped but impossible) can no longer be mistaken for the output of a failed hash. The OpenSSH team is explicit that this is a workaround: "We consider the root cause of this bug to be outside sshd." The root cause — musl's * sentinel — is unchanged as of this writing. And the 10.6p2 release bundles a little more than the workaround: the new post-quantum hybrid CA signature scheme ssh-mldsa44-ed25519, a fix for a <1-second CPU spin with ChannelTimeout, and the beginning of the end for scp's fragile -R remote-to-remote flag.
Alpine's fix matrix deserves a moment of respect: they backported to every branch, including five (3.16–3.20) that are past end-of-support. The table runs from 10.6_p2-r0 on edge down to 9.0_p1-r6 on 3.16. And there's an operational trap the advisory calls out twice: upgrading the package does not restart the running sshd. apk upgrade followed by rc-service sshd restart — or the process keeps serving the vulnerable code.

The Part That Should Change How You Think About Security Work
The bug is great copy. The discovery method is the actual news.
Kültekin's write-up describes the process: build sshd in every configuration that matters — glibc, musl, PAM, no PAM, shadow, no shadow — and hammer every build with weird logins. Weird hashes. Broken accounts. Passwords far too long. Around 17,600 of them. Every build agreed on every login — except musl-without-PAM, which kept saying yes to things it should have said no to.
And then there's this line, delivered with admirable understatement: "oh did i say 'i'? sorry. i had agent swarms. a lot of them. let's not get into it."
That's the new shape of vulnerability research: an human directing fleets of AI agents to fuzz the seams between components — the code "people don't really look at... they look at the crypto."
The OpenSSH team's response is equally telling. Their 10.6p2 release notes contain a paragraph that deserves to be quoted in every security team's onboarding deck:
"Recently the OpenSSH team have received a large number of security bug reports, many of which are findings from AI models or made with AI assistance... We have seen a number of cases where a security bug identified by AI tools is subsequently independently discovered by a different researcher. This suggests that adversaries who do not report bugs to OSS projects are likely to be able to discover these bugs too. Given this, the OpenSSH team will, for now, be making more frequent releases to get bugfixes into users' hands more quickly rather than batching them until the next planned release."
Damien Miller — OpenSSH's lead developer — said the same thing in public the same day, blunter: the team learned of the problem "yesterday" and shipped as fast as it could, because "we have recently observed multiple cases of rapid bug rediscovery by AI agents, sometimes within hours, and so now consider long embargo periods to be a dangerous practice that primarily benefits attackers."
Sit with that. The coordinated-disclosure model — report, embargo, patch on a schedule — has been the polite architecture of open-source security for decades. Its quiet assumption is that a secret is keepable: the finder holds the bug, maintainers get weeks or months, and the window stays closed to adversaries because nobody else can find the thing. AI just broke that assumption at the seams. If a friendly agent swarm re-derives a bug within hours of its discovery, then the embargo isn't a shield — it's a head start you're handing to whoever isn't playing nice. OpenSSH is the highest-stakes project to say it out loud and change its release cadence in response.
There's an irony nested in the irony: OpenSSH 10.6p1 shipped a month ago (October 6) carrying changes made with AI assistance — including a security fix credited "With Chris Rohlf in collaboration with Claude and Anthropic Research" — and the release notes' AI-acknowledgment paragraph appeared in both releases. The same technology that's flooding maintainers with noise is finding decade-old criticals and compressing patch timelines from months to a day. Both of those things are true at once, and the teams doing the most important infrastructure work on the planet are learning to live with the contradiction.
What This Changes
If you run Alpine in production — tonight, not next sprint. The advisory's own words: "If you run sshd on Alpine Linux, update openssh now and restart sshd." apk upgrade -U -a then rc-service sshd restart (3.21.10 / 3.22.8 / 3.23.8 / 3.24.4 and edge carry the fix; older branches have their own fixed packages back to 3.16). Can't update? Disable password authentication — PasswordAuthentication no — which the advisory confirms "closes the hole," with a full drop-in config recipe. And if you can't rule out that someone used the bypass, the advisory's guidance is unambiguous: "treat the machine as compromised." Check /var/log/messages for Accepted password lines on accounts that shouldn't have passwords — alpine, root, key-only users — and review doas usage, new users, and authorized keys. The disclosure site also links a checker at github.com/oz9un/sshole, though the OX Security write-up sensibly warns against running unverified exploit scripts from social media.
If you build images, rebuild them. Patching running instances doesn't fix the baked image. Any Dockerfile, VM template, or AMI descending from a pre-fix Alpine base needs a rebuild-and-redeploy cycle, because the bug ships inside the artifact.
For the rest of us, this is a signal about the next five years. The boring glue code — the contracts between libc and daemons, the sentinel values, the error paths nobody reads — is now the most attractive attack surface in software, because it's exactly where human review is thinnest and automated differential testing is cheapest. OpenSSH's own release notes already treat AI-sourced reports as a firehose to be triaged ("we very much welcome these reports, especially when combined with human triage, analysis, test-cases and particularly when accompanied by proposed fixes"). Expect every serious infrastructure project to face the same choice OpenSSH just made: ship fixes in days, or watch agents re-find them.
⚠️ Limitations & Caveats
- No CVE (in the official advisories, anyway). Alpine's advisory states plainly: "No CVE identifier had been assigned at the time of writing." One vendor report labels the flaw CVE-2026-123158 with CVSS v3.1 8.1 High — but OpenSSH and Alpine don't use that identifier in their official communications, so treat the CVE as vendor-assigned, not canonical.
- No known exploitation — with an asterisk. Miller says no attacks using the flaw have been reported. But the disclosure's own honest framing stands: this bug leaves successful logins that look perfectly normal, ten years of exposure means forensic confidence is inherently limited, and "as far as anyone knows, nobody noticed. as far as anyone knows."
- The workaround, not the cure. OpenSSH's fix is explicitly a workaround; musl's
crypt()still returns*on failure. Any other consumer ofcrypt()with the same compare-the-star pattern is theoretically still exposed — sshd is just the one that mattered and got patched. - The blast radius is narrower than the headline. This is not "the internet is broken." glibc systems, PAM users, Dropbear, OpenBSD, locked
!accounts, password-auth-off systems, and sshd-less containers are all unaffected. The exposure is concentrated in musl-no-PAM deployments — which is precisely why Alpine got fixed packages for ten branches in a day. - Bytes, not characters. The precise trigger is 257–1,024 bytes of password (musl's 256-byte cap at one end, sshd's 1,024-byte limit at the other). Some summaries say "characters"; the advisory's byte language is the authoritative one.
- 17,600 logins is the finder's own figure. The test volume and the "agent swarms" description come from the disclosure site itself. It's the best account of the discovery we have — but it is one researcher's self-report, not an audited methodology.
🎯 The Bottom Line
Four defensible decisions — a crash-proof sentinel, a DoS cap, a timing-equalization hack, and a friendlier root lock — fused into a one-try master key that sat in plain sight for fourteen years, guarded only by the fact that nobody reads the glue. It took agent swarms and 17,600 weird logins to find it, and it took OpenSSH one day to ship the fix, because AI has made the old embargo math untenable. Patch your Alpine boxes tonight, restart sshd after the upgrade, and update your mental model: the frontier of security research is no longer a person with a debugger — it's a person with a swarm.
📚 Sources
- sshhole.com — the disclosure — Özgün Kültekin of Wakefield's full interactive write-up: the 1980 asterisk, the 2012 musl commits (
b3c4cc12,88bf5a8a), the 2016 salt-borrowing fix, Alpine's 2022root:*, the build matrix and ~17,600 adversarial logins. https://sshhole.com - OpenSSH Release Notes — 10.6p2 (2026-11-05) — Official notes: "critical security workaround that affects Linux systems that use the musl libc and PAM disabled"; root cause outside sshd; the AI-reports paragraph and release-cadence change; checksums. https://www.openssh.org/releasenotes.html
- Alpine Linux Security Advisory (2026-11-05) — Official advisory: four-condition exposure list, 257–1024 byte trigger, affected releases 3.16→edge, the full fix-version table, tiny-cloud
doasescalation path, detection and remediation commands. https://alpinelinux.org/posts/2026-11-05-openssh-password-authentication-bypass/ - Damien Miller on Hachyderm (2026-11-05) — OpenSSH lead developer: learned of the problem "yesterday"; "IMMEDIATELY" guidance; AI rapid-rediscovery; embargoes now "a dangerous practice that primarily benefits attackers." https://hachyderm.io/@damienmiller/117563026759098135
- The Hacker News (2026-11-05) — Swati Khandelwal's coverage: critical rating, "No attacks using the flaw have been reported," the four-condition exposure list, the <4-character fix description, OpenWrt/Dropbear context. https://thehackernews.com/2026/11/openssh-issues-emergency-fix-for-flaw.html
- OX Security (2026-11-05) — Technical analysis with the vendor-assigned CVE-2026-123158 and CVSS 8.1; step-by-step bypass sequence; rebuild-your-images guidance. https://www.ox.security/blog/openssh-authentication-bypass-cve-2026-123158/
- Hacker News — community signal — Story "sshole" (50378228): 2,823 points / 688 comments on the front page at time of writing (2026-11-06, via HN Algolia API). https://news.ycombinator.com/item?id=50378228
All claims verified against Gold-tier (official OpenSSH release notes, Alpine Linux advisory, the finder's primary disclosure, and OpenSSH's lead developer's own post) and Silver-tier (The Hacker News, OX Security) sources. Each source URL was scraped and confirmed accessible; conflicting details (CVE status, bytes vs characters) are noted in the body. Community figures (HN points) labeled as community-sourced. Last verified: November 6, 2026.