A one-line password bypass hit Alpine's sshd. I built a 5-condition check that tells you if your images are exposed.
On November 5, Alpine Linux published an urgent advisory: a password authentication bypass in OpenSSH, tracked as CVE-2026-123158, CVSS 8.1 High. An attacker who can reach your SSH port can log in without knowing any pas
On November 5, Alpine Linux published an urgent advisory: a password authentication bypass in OpenSSH, tracked as CVE-2026-123158, CVSS 8.1 High. An attacker who can reach your SSH port can log in without knowing any password β send a 257β1024 byte password, and musl's crypt() returns "*", matching the stored "*" field of an account that has no password set. OpenSSH shipped 10.6p2 the same day as a critical workaround. By November 6, watchTowr reported active exploitation attempts, driven by automated botnets and cryptominers.
The catch: a CVE list cannot tell you whether your images are exposed. The bypass only fires when five conditions hold at once β Alpine with musl, OpenSSH without PAM, password authentication on, a * account, and a $5$/$6$ salt donor somewhere on the box. A scanner that checks the CVE database answers a different question. I built alpinegate to answer the one that matters: which of my images actually run this combination?
What it does
alpinegate checks the five live conditions from the image itself, with zero network and no database wait, and returns one verdict per target: EXPOSED, AT-RISK, SAFE, or UNKNOWN (UNKNOWN is never SAFE).
alpinegate scan fixtures/exposed fixtures/patched
Targets can be a rootfs directory, a .tar / .tar.gz, a docker-save tarball, or a local Docker image through the daemon socket (read-only). There is also check for a single target and playbook, which prints the first-hour stopgap: close password logins, upgrade and restart the daemon, then check whether you were already attacked. The tool never attempts an SSH login, ships no exploit code, and never edits a config or restarts a daemon β the playbook only prints steps.
The demo below runs the real CLI against real fixtures β an Alpine 3.18.9 minirootfs with the real vulnerable openssh 9.3_p2-r3 and the real fixed 9.3_p2-r4:
And the scan output, captured from the real CLI:
$ alpinegate scan fixtures/exposed fixtures/patched
TARGET ALPINE OPENSSH PAM PASSAUTH `*` ACCOUNTS DONOR VERDICT
---------------- ------ --------- --- -------- ------------ ----- -------
fixtures/exposed 3.18.9 9.3_p2-r3 no yes root $6$ EXPOSED
fixtures/patched 3.18.9 9.3_p2-r4 no yes root $6$ SAFE
fixtures/exposed: all five conditions hold: Alpine 3.18, openssh 9.3_p2-r3 < fixed 9.3_p2-r4, no PAM, password auth on, * accounts (root) + $6$ salt donor
fixtures/patched: openssh 9.3_p2-r4 is at or above the fixed version 9.3_p2-r4 for Alpine 3.18
exit: 1
Two details worth noting. The fixed-version map is taken from the Alpine advisory itself, per branch from 3.16 to edge, with the source URL and check date recorded in the code β a wrong map here would mean a false SAFE, the worst possible failure, so every branch value is pinned by a unit test. And the tool only ever records the $5$/$6$ hash-type prefix, never a hash β an end-to-end test asserts the real fixture hash is absent from CLI output.
Use it as a CI gate
Scan your images before they ship, and fail the build on EXPOSED:
- run: node dist/cli.js scan ./image.tar --fail-on exposed
Exit codes are 0 (no EXPOSED), 1 (EXPOSED found, or AT-RISK with --fail-on at-risk), 2 (usage error).
Where rivals beat us
I compared against the closest tools before building, and alpinegate loses on their home turf:
- Trivy and Grype beat alpinegate on breadth: they cover thousands of CVEs across every package in an image, plus IaC, Kubernetes, secrets, and licenses. alpinegate covers exactly one exposure shape. If you want a full CVE list, use Trivy or Grype.
-
ssh-audit beats alpinegate on SSH policy depth: it audits configuration and policy in detail. It does not detect Alpine/musl, does not check
/etc/shadow, and does not inventory a fleet. - Lynis / OpenSCAP beat alpinegate on host hardening breadth: full audits across the whole host. They have no sshole-specific condition check and no container inventory.
The wedge: Trivy and Grype are database-driven, so a same-day CVE may not be in their database yet. On the day this CVE landed, a condition checker was not blind in the same way. alpinegate checks the five live conditions from the image itself, with zero network and no database wait, and adds an image inventory plus a first-hour playbook that a CVE list does not give you.
Honest limits
-
Conditions, not exploitability. EXPOSED means the bypass shape is present; it does not prove anyone logged in. Check
/var/log/messagesforAccepted passwordentries for that. -
UNKNOWN is not SAFE. If the tool cannot read
/etc/shadowor the package database, it says UNKNOWN β treat it as "go look", not as a pass. -
Global sshd_config context only.
Matchblocks are not parsed yet; the README tells you to verify withsshd -T. Match-aware parsing is on the roadmap. -
Static images cannot tell you the daemon state. Whether sshd is actually running is reported as unknown for image targets; a live-host scan checks
/proc. - No registry pull, no Kubernetes inventory, no GitHub Action wrapper yet. Those are roadmap items, listed honestly in the README.
- The fixed-version map is dated. It was checked against the Alpine advisory on 2026-11-06. If Alpine publishes new backports, the map needs a re-check β the code records the check date so you can see it.
Install
Install from source for now (no published npm package yet):
git clone https://github.com/techdevfun/alpinegate.git
cd alpinegate
npm install
npm run build
node dist/cli.js --help
Node 20 or later. Zero runtime dependencies. TypeScript, strict mode. The test suite is 35 tests (25 unit, 10 end-to-end) plus a live smoke test, and CI runs it on Node 20 and 22.
Sources
CVE-2026-123158, CVSS 3.1 8.1 (High). Researcher: ΓzgΓΌn KΓΌltekin (Wakefield); write-up at sshhole.com. Alpine advisory 2026-11-05; OpenSSH 10.6p2 released 2026-11-05. watchTowr active exploitation attempts reported 2026-11-06.
The code is MIT licensed at github.com/techdevfun/alpinegate. If you run Alpine images anywhere, scan them before the weekend β the botnets already started.
Originally published by Dev.to Security. Aggregated on AIWithGhost for educational purposes β full credit and traffic to the original publisher.