A misplaced list-splitter turns a comma into a skeleton key for every server that trusts your CA
CVE-2026-35414, dubbed SplitSSHell by its discoverers at Cyera, is an authentication-bypass flaw in OpenSSH's authorized_keys certificate principal matching. The bug lived in auth2-pubkeyfile.c for roughly 15 years (OpenSSH 5.6 through 10.2p1). When a CA key is trusted via a cert-authority,principals="admin,deploy" line in authorized_keys, the server calls match_list() — a function designed to split comma-delimited negotiation strings — instead of strcmp() to compare certificate principals against the allowed list. An attacker who can obtain a certificate with the principal deploy,root (a single string containing a literal comma) causes the parser to split on the comma and match root as a separate, valid principal. The attacker then gets a root shell. The main certificate path (TrustedUserCAKeys / AuthorizedPrincipalsFile) is not affected.
The vendor-assigned CVSS of 4.2 MEDIUM dramatically underweights the actual impact. The vendor vector scores confidentiality and integrity as *Low* (C:L/I:L), which is indefensible when the documented outcome is *root access with zero authentication-failure logging*. NVD scored it 8.1 HIGH with C:H/I:H/A:H, which correctly captures impact but arguably over-scores reachability by setting PR:N — the attacker does need a valid certificate (at minimum PR:L). Red Hat split the difference at 4.8 Moderate, noting certificates aren't default. The real story is that the impact is catastrophic *when the chain lands*, but the preconditions — SSH certificate auth via cert-authority in authorized_keys, plus a CA willing to sign comma-containing principals — genuinely narrow the exposed population. Neither the vendor's 4.2 nor the NVD's 8.1 captures this correctly.
4 steps from start to impact.
Attacker holds a valid user certificate
ssh-keygen -s or an automated signing API (Teleport, Vault SSH, step-ca, Smallstep). The attacker needs no special privileges beyond normal cert-request access.- Organization uses SSH certificate-based authentication
- Attacker has access to a certificate-signing workflow
- SSH certificate auth adoption is estimated at 5–15% of enterprises
- Many orgs use TrustedUserCAKeys (unaffected path) rather than cert-authority in authorized_keys
Craft a certificate with a comma-embedded principal
deploy,root — a single principal containing a literal comma. If the CA does not enforce a character allowlist on principal names (many don't — ssh-keygen -s accepts arbitrary strings), the CA signs and returns the certificate. No exploit tooling is required; standard ssh-keygen suffices. Cyera researchers reported going from concept to root shell in ~20 minutes.- CA does not validate or restrict characters in requested principal names
- Target server trusts this CA via cert-authority in authorized_keys with a principals= restriction
- Well-managed CAs (Vault, Teleport with RBAC) enforce principal allowlists that would reject commas
- Small or ad-hoc CAs using raw ssh-keygen -s are most exposed
Present the malicious certificate to the target sshd
ssh -i crafted_cert -o CertificateFile=crafted_cert-cert.pub root@target. The vulnerable match_principals_option() function calls match_list(), which splits the certificate principal deploy,root on the comma. The result is two tokens: deploy and root. If root appears in the principals= list on the cert-authority line — or if the match against the target username succeeds — authentication is granted.- Target sshd runs OpenSSH < 10.3 without a distro backport patch
- Target's authorized_keys contains a cert-authority line with principals= listing the target username
- Patched distro packages are available for Ubuntu 14.04–26.04, RHEL, Debian, SUSE, etc., reducing the unpatched window
- Servers using only TrustedUserCAKeys are immune
Root shell obtained — lateral movement begins
cert-authority in authorized_keys is equally vulnerable, the attacker can repeat the attack across the fleet. Root access enables credential harvesting, persistence via backdoor keys, and pivot to internal services. The lack of authentication-failure logging makes forensic detection significantly harder.- Attacker has network reachability to additional servers trusting the same CA
- Network segmentation and microsegmentation limit lateral reach
- Host-based EDR (CrowdStrike, SentinelOne, Carbon Black) may detect post-exploitation behavior even if the auth bypass is invisible
match_list() with strsep() + strcmp() in match_principals_option(). Distro backport packages are available for Ubuntu 14.04–26.04, RHEL, Debian, SUSE, and others. Apply within the noisgate remediation SLA of 180 days for HIGH (or sooner if cert-authority is actively used). Test in staging first — the fix also changes wildcard handling for certificate principals.cert-authority directives in all ~/.ssh/authorized_keys files. Remove entries that are no longer needed or that were added as convenience shortcuts. Each removed entry eliminates one trust path for the attack. Combine with migration to TrustedUserCAKeys. Deploy within 30 days per noisgate mitigation SLA.- Fail2ban / rate-limiting SSH — the attack succeeds on the *first* connection attempt with a valid certificate. There are no failed authentications to trigger a ban.
- SSH key rotation — this vulnerability is in the *certificate* authentication path, not the public-key path. Rotating SSH keys does not affect certificate trust.
- Log-based auth-failure monitoring (alone) — Cyera confirmed the server treats the malicious authentication as legitimate. No
Failed passwordorFailed publickeyentry is generated. You must monitor for anomalous *successful* sessions instead. - Network-level SSH restriction (alone) — if the attacker is an authenticated insider with legitimate SSH access, firewall rules that permit their SSH traffic will also permit the exploit. This helps only if it blocks the attacker from reaching additional cert-authority-trusting servers.
The supporting signals.
| In-the-wild exploitation | No confirmed active exploitation. Not listed on CISA KEV. No GreyNoise tags or Shadowserver scan activity reported as of 2026-09-27. CIS rated it HIGH for large entities but noted no campaigns. |
|---|---|
| Proof-of-concept availability | Yes — multiple sources. dehobbs/cve_2026_35414 on GitHub provides an auditing/detection tool with Docker-based reproduction. Exploit Intelligence Platform ships a full lab with Dockerfiles, cert builders, and multiple PoC vectors. Cyera (discoverers) demonstrated root-in-20-minutes but have not released weaponized code. No Metasploit or Nuclei module at time of writing. |
| EPSS | 0.00243 (0.243%), approximately 7th percentile. Indicates low predicted exploitation probability in the next 30 days, consistent with the narrow preconditions. |
| CISA KEV status | Not listed. No deadline-driven federal patching mandate. |
| CVSS vector analysis | Vendor vector CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:L/I:L/A:N = 4.2. NVD vector CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H = 8.1. The NVD vector correctly captures the root-access impact (C:H/I:H) but debatably sets PR:N — a valid cert is required. The vendor vector's C:L/I:L is incorrect: root access is not 'low' impact. |
| Affected versions | OpenSSH 5.6 through 10.2p1 (approximately 15 years of releases). Only the cert-authority + principals= path in authorized_keys is affected. TrustedUserCAKeys / AuthorizedPrincipalsFile paths are not vulnerable. |
| Fixed versions (incl. backports) | Upstream: OpenSSH 10.3 / 10.3p1 (2026-04-02). Ubuntu: 26.04 1:10.2p1-2ubuntu3.2, 25.10 1:10.0p1-5ubuntu5.4, 24.04 1:9.6p1-3ubuntu13.16, 22.04 1:8.9p1-3ubuntu0.15, 20.04 1:8.2p1-4ubuntu0.13+esm3, 18.04 1:7.6p1-4ubuntu0.7+esm6. RHEL/Fedora: errata available (see bugzilla#2454490). |
| Internet exposure | Shodan indexes tens of millions of OpenSSH instances internet-facing. However, the vulnerable *configuration* (cert-authority in authorized_keys with principals=) is a small subset. No Shodan/Censys query can distinguish the vulnerable configuration from the outside — banner version is the only signal. |
| Disclosure & credit | Disclosed 2026-04-02 alongside the OpenSSH 10.3 release. Discovered by the Cyera research team, who dubbed it SplitSSHell. The root cause was a call to match_list() instead of strcmp() in match_principals_option() in auth2-pubkeyfile.c. |
| Related advisories | CIS Advisory 2026-040 (HIGH for large orgs), Belgian CCB (Patch Immediately), GHSA-f6c7-fj8h-5898, Red Hat CVE page (Moderate 4.8). |
Sources.
- OpenSSH 10.3 Release Notes
- SecurityWeek — OpenSSH Flaw Allowing Full Root Shell Access Lurked for 15 Years
- CIS Advisory 2026-040 — OpenSSH Authentication Bypass
- Red Hat CVE-2026-35414 Advisory
- Ubuntu CVE Tracker — CVE-2026-35414
- Penligent — CVE-2026-35414 Technical Analysis
- dehobbs/cve_2026_35414 — Exposure Auditor (GitHub)
- Red Hat Bugzilla #2454490
Why this verdict
- Impact floor: root access, zero log trail. The vendor's C:L/I:L impact scoring is factually wrong. When the chain lands, the attacker gets a root shell and the server logs it as a *successful, legitimate authentication*. This is C:H/I:H minimum, and the vendor CVSS must be upgraded on impact alone.
- Role multiplier: OpenSSH is canonical high-value infrastructure. OpenSSH is the remote-access layer for virtually all Linux/Unix hosts — production databases, CI/CD runners, Kubernetes nodes, bastion/jump servers, backup targets. In environments using cert-authority in authorized_keys, every trusting server is equally exploitable. The blast radius is fleet-scale root when the chain fires: the attacker repeats the same cert against every host trusting the CA. This role analysis sets a floor of HIGH because the affected component *is* the access control layer for high-value roles, and the cert-authority configuration, while uncommon overall, represents >1% of the OpenSSH installed base in certificate-using enterprises.
- Friction is real but not disqualifying. SSH certificate authentication is a minority practice (~5–15% of enterprises). Of those, the vulnerable path (cert-authority in authorized_keys rather than TrustedUserCAKeys) is the less recommended option but is still actively used, especially in older deployments predating TrustedUserCAKeys adoption. The CA must sign comma-containing principals, which is trivial with unmanaged CAs (raw ssh-keygen -s) but blocked by well-configured enterprise CAs (Vault, Teleport). These friction points prevent this from reaching CRITICAL but do not justify dropping below HIGH.
- PoC exists and exploitation is trivial. Cyera demonstrated root in 20 minutes with standard tooling (ssh-keygen, ssh). The dehobbs GitHub repo provides a detection/audit tool, and the Exploit Intelligence Platform ships a full reproduction lab. No specialized exploit framework is needed — only a standard SSH client and a signed certificate.
- 15-year exposure window. The vulnerable code has been present since OpenSSH 5.6, meaning every unpatched server from the last ~15 years is technically in scope if the configuration matches. Distro backports are available but adoption varies.
Why not higher?
CRITICAL would require the vulnerable configuration to be the *default* or near-universal. It is not. SSH certificate authentication is opt-in, and the specific cert-authority + principals= pattern in authorized_keys is the less common of the two certificate trust paths. The attacker also needs a valid certificate from a trusted CA — they must already be an authenticated insider or have compromised a signing workflow. These compounding preconditions keep the real-world exploitable population narrow enough that CRITICAL overstates the fleet-wide risk.
Why not lower?
MEDIUM would require the impact to be limited or the attack impractical. Neither is true. The impact is root access with no authentication-failure logging — the gold standard of access-control bypasses. The attack requires no specialized tooling and has a working PoC. The 15-year exposure window means a massive backlog of unpatched versions exists. CIS rated this HIGH for large organizations, and the Belgian CCB issued a 'Patch Immediately' advisory. Dropping to MEDIUM would ignore the floor set by OpenSSH's role as the canonical access-control layer for all Unix/Linux infrastructure.
Crowdsourced verification payload.
Run this script on each target host as root (or a user with read access to /etc/ssh/sshd_config and all users' ~/.ssh/authorized_keys). Invoke with: sudo bash cve_2026_35414_check.sh. No arguments required. Exit code 0 = PATCHED, 1 = VULNERABLE, 2 = UNKNOWN.
#!/usr/bin/env bash
# CVE-2026-35414 Exposure Auditor — SplitSSHell
# Checks OpenSSH version + cert-authority config exposure
# Exit: 0=PATCHED 1=VULNERABLE 2=UNKNOWN
set -uo pipefail
RESULT="UNKNOWN"
FIXED_MAJOR=10
FIXED_MINOR=3
VERSION_STRING=""
# --- Step 1: Determine OpenSSH version ---
if command -v sshd >/dev/null 2>&1; then
VERSION_STRING=$(sshd -V 2>&1 | grep -oP 'OpenSSH_\K[0-9]+\.[0-9p]+' || true)
fi
if [[ -z "$VERSION_STRING" ]] && command -v ssh >/dev/null 2>&1; then
VERSION_STRING=$(ssh -V 2>&1 | grep -oP 'OpenSSH_\K[0-9]+\.[0-9p]+' || true)
fi
if [[ -z "$VERSION_STRING" ]]; then
echo "UNKNOWN — could not determine OpenSSH version"
exit 2
fi
MAJOR=$(echo "$VERSION_STRING" | cut -d. -f1)
MINOR=$(echo "$VERSION_STRING" | cut -d. -f2 | sed 's/p.*//')
echo "[*] OpenSSH version: $VERSION_STRING"
# --- Step 2: Version comparison ---
if [[ "$MAJOR" -gt "$FIXED_MAJOR" ]] || \
{ [[ "$MAJOR" -eq "$FIXED_MAJOR" ]] && [[ "$MINOR" -ge "$FIXED_MINOR" ]]; }; then
echo "[+] Version >= 10.3 — not vulnerable"
RESULT="PATCHED"
else
# Check for distro backport patches
BACKPORTED=false
if command -v dpkg >/dev/null 2>&1; then
PKG=$(dpkg -s openssh-server 2>/dev/null | grep '^Version:' | awk '{print $2}' || true)
if [[ -n "$PKG" ]]; then
echo "[*] Debian/Ubuntu package: $PKG"
if zgrep -q 'CVE-2026-35414' /usr/share/doc/openssh-server/changelog.Debian.gz 2>/dev/null; then
BACKPORTED=true
fi
fi
fi
if command -v rpm >/dev/null 2>&1 && [[ "$BACKPORTED" == false ]]; then
PKG=$(rpm -q openssh-server 2>/dev/null || true)
if [[ -n "$PKG" ]]; then
echo "[*] RPM package: $PKG"
if rpm -q --changelog openssh-server 2>/dev/null | head -200 | grep -q 'CVE-2026-35414'; then
BACKPORTED=true
fi
fi
fi
if $BACKPORTED; then
echo "[+] Distro backport patch for CVE-2026-35414 detected"
RESULT="PATCHED"
else
RESULT="VULNERABLE"
echo "[-] Version $VERSION_STRING < 10.3 — VULNERABLE"
fi
fi
# --- Step 3: Configuration exposure (only if vulnerable) ---
if [[ "$RESULT" == "VULNERABLE" ]]; then
echo ""
echo "--- Configuration Exposure ---"
CERT_AUTH_COUNT=0
while IFS=: read -r _user _ _ _ _ home shell; do
[[ "$shell" == */nologin || "$shell" == */false ]] && continue
AK="$home/.ssh/authorized_keys"
if [[ -r "$AK" ]] && grep -q 'cert-authority' "$AK" 2>/dev/null; then
HITS=$(grep -c 'cert-authority' "$AK" 2>/dev/null || echo 0)
PRINS=$(grep 'cert-authority' "$AK" | grep -c 'principals=' 2>/dev/null || echo 0)
echo " [!] $AK: $HITS cert-authority line(s), $PRINS with principals="
CERT_AUTH_COUNT=$((CERT_AUTH_COUNT + HITS))
fi
done < /etc/passwd
TRUSTED_CA=false
if [[ -r /etc/ssh/sshd_config ]] && grep -qi '^[[:space:]]*TrustedUserCAKeys' /etc/ssh/sshd_config 2>/dev/null; then
TRUSTED_CA=true
echo " [i] TrustedUserCAKeys configured in sshd_config (NOT affected by this CVE)"
fi
echo ""
if [[ $CERT_AUTH_COUNT -gt 0 ]]; then
echo "VULNERABLE — unpatched AND cert-authority in authorized_keys detected"
echo "This host is DIRECTLY EXPOSED to CVE-2026-35414."
else
echo "VULNERABLE — unpatched, but no cert-authority usage found"
echo "Exposure is LOW unless cert-authority is added. Patch recommended."
fi
fi
echo ""
echo "$RESULT"
case "$RESULT" in
PATCHED) exit 0 ;;
VULNERABLE) exit 1 ;;
*) exit 2 ;;
esac