The bouncer is checking IDs but forgot to look at the hologram — anyone with a printer gets a technician badge
SimpleHelp's OIDC login flow accepts an identity token from the configured provider but never validates the cryptographic signature on it (CWE-347). That means an unauthenticated attacker on the internet can hand-craft a JWT claiming to be any technician, hand it to the server, and walk away with a fully authorized technician session — which by default includes remoting into every managed endpoint, pushing scripts, and creating new privileged accounts. Affected builds are SimpleHelp ≤ 5.5.15 on the stable channel and all 6.0 pre-release builds; fixes are in 5.5.16 and 6.0 RC2. MFA does not save you — first-login self-enrollment means the attacker enrolls their own factor.
Vendor's CRITICAL/9.8 rating is accurate and arguably understated for the deployment role. SimpleHelp is an RMM — by definition a privileged egress point into hundreds or thousands of downstream endpoints — and the bug is pre-auth, network-reachable, low-complexity, with scope change and full CIA impact. CISA KEV listed it on 2026-06-29 with a 14-day federal remediation deadline; Djinn Stealer is being dropped on victims in the wild. Friction is essentially zero.
4 steps from start to impact.
Locate exposed SimpleHelp server
/allconfig/oidc or login page advertises an OIDC button.- Internet reachability to the SimpleHelp web port (typically 443/8443)
- Target has OIDC enabled (~7.2% of exposed servers per Horizon3 sampling)
- Servers behind VPN-only access are not directly reachable
- Some MSPs deploy SimpleHelp on private IPs with reverse-proxy ACLs
Forge an OIDC ID token
iss, sub, email, and group claims matching a valid TechnicianGroup mapped to the OIDC provider. Because SimpleHelp skips signature verification, the JWT can be signed with alg:none or any throwaway key. Public PoC scaffolding exists in Horizon3's disclosure write-up and is trivially reproducible with pyjwt or jwt.io.- Knowledge of the OIDC provider issuer string (often discoverable from the login page)
- Knowledge of at least one valid group name (often guessable or leaked)
- None meaningful — claim values are often defaults or organization-name-derived
Submit token, obtain technician session
- TechnicianGroup has 'Allow group authenticated logins' enabled (the default for OIDC-bound groups)
- Operators who manually pre-provisioned every technician account AND disabled self-registration block self-enrollment of MFA — rare in MSP deployments
Pivot to managed endpoints
- At least one online SimpleHelp endpoint agent in the target tenant
- Application-allowlisting on endpoints can block unsigned payloads
- EDR may catch Djinn Stealer's known IOCs
Remote Access.exe / SimpleService.exe spawning child processes that drop unfamiliar binaries; Horizon3 published IOC hashes.The supporting signals.
| In-the-wild | Active exploitation confirmed — BlackPoint Cyber APG flagged campaigns dropping Djinn Stealer on 2026-06-29 |
|---|---|
| KEV status | Listed 2026-06-29, federal due date 2026-07-13 (14-day window) |
| Public PoC | Technical write-up with reproduction details published by Horizon3.ai (horizon3.ai/attack-research/vulnerabilities/cve-2026-48558); JWT forging is trivial with pyjwt |
| EPSS | 0.00721 (low percentile, but EPSS lags hours-old KEV adds — disregard here) |
| CVSS vector | CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H = 9.8 — pre-auth network RCE-equivalent with scope change |
| Affected versions | SimpleHelp ≤ 5.5.15 stable and all 6.0 pre-release builds |
| Fixed versions | 5.5.16 (stable) and 6.0 RC2 (pre-release) |
| Exposure | ~14,000 internet-exposed SimpleHelp servers (Daily Security Review, Jun 2026); ~7.2% have OIDC enabled per Horizon3 sampling → ~1,000 directly exploitable instances |
| Disclosed | 2026-06-12 (Horizon3.ai) |
| Reporter | Horizon3.ai Attack Team |
noisgate verdict.
The single decisive factor is role multiplier: SimpleHelp is an RMM, so a pre-auth signature-skip on its login plane converts directly into fleet-scale remote code execution on every downstream managed endpoint. Active KEV exploitation with infostealer payloads eliminates any argument for a lower bucket.
Why this verdict
- Role multiplier: SimpleHelp's high-value role IS its only role — every install is an RMM with admin reach into managed endpoints. The chain ends in fleet compromise on success, not just server compromise. This is canonical CRITICAL floor territory (cf. Kaseya VSA, ConnectWise ScreenConnect CVE-2024-1709).
- Pre-auth, network-reachable, low-complexity: the attacker needs nothing but the URL and a forged JWT — no credentials, no user interaction, no internal foothold.
- KEV-listed and actively exploited: Djinn Stealer campaigns observed, CISA 14-day deadline issued. Any downgrade argument dies here.
- Friction is minimal: the ~7.2% OIDC-enabled subset still represents ~1,000 directly exposed servers, each fronting hundreds of endpoints. The bug also affects pre-release 6.0 admins who think they're safe on the new train.
- MFA bypass built into the same flaw: first-login self-enrollment means defenders who thought MFA was their compensating control are wrong.
Why not higher?
9.8 is already the practical ceiling for a remote-code-equivalent CVSS 3.1 score. There is no defensible move to 10.0 without changes to the scoring rubric.
Why not lower?
Every friction lever a defender would cite — auth requirement, narrow population, no PoC, no KEV — is absent here. Pre-auth, public detail, KEV-listed, active campaigns, RMM blast radius. Downgrading would be malpractice.
What to do — in priority order.
- Disable OIDC on the SimpleHelp server until patched — In the SimpleHelp admin console under Authentication, switch OIDC off and force technicians to local credentials + MFA. This removes the vulnerable code path entirely. Do this within hours — the noisgate mitigation SLA for CRITICAL is ≤ 3 days but active KEV exploitation overrides that to immediate.
- Block internet access to the SimpleHelp web UI — If the server has no business being public, put it behind a VPN, Cloudflare Access, or a source-IP allowlist for your technicians' egress. Most MSPs do not need world-readable RMM consoles. Implement within hours.
- Upgrade to SimpleHelp 5.5.16 (or 6.0 RC2 if on the pre-release channel) — This is the actual fix. Patch deployment per the noisgate remediation SLA for CRITICAL is ≤ 90 days, but given KEV listing this collapses to immediate — schedule the upgrade tonight, not next sprint.
- Rotate every technician credential and revoke all existing sessions — Assume sessions were created; force re-authentication after patching. Audit the technician roster for accounts you did not create.
- Hunt for indicators of compromise from Horizon3 + BlackPoint — Pull SimpleHelp audit logs for unexpected technician logins since 2026-06-12, look for new MFA enrollments on existing accounts, and scan managed endpoints for Djinn Stealer IOCs.
- MFA enforcement — the bypass also defeats first-login MFA self-enrollment; turning MFA on is necessary hygiene but does not block this CVE.
- WAF rules on JWT length / shape — the forged token is structurally valid; only signature verification catches it, and the server isn't doing that.
- Egress filtering on managed endpoints — the attacker is operating *through* your trusted RMM channel; the traffic looks legitimate to network controls.
- EDR alone — Djinn Stealer is one observed payload; the attacker can drop arbitrary tooling via the technician console, and the SimpleHelp agent process is on most EDR allowlists.
Crowdsourced verification payload.
Run on an auditor workstation that can HTTP-reach the SimpleHelp server. Invoke as ./check_simplehelp.sh https://rmm.example.com. No privileges required; this only reads the public version banner.
#!/usr/bin/env bash
# noisgate check for CVE-2026-48558 (SimpleHelp OIDC signature-skip auth bypass)
# Output: VULNERABLE / PATCHED / UNKNOWN
set -u
TARGET="${1:-}"
if [[ -z "$TARGET" ]]; then
echo "usage: $0 https://simplehelp.example.com" >&2
exit 2
fi
# SimpleHelp exposes its version at /allconfig/info or in the page footer
RESP=$(curl -ksS --max-time 10 "$TARGET/allconfig/info" || true)
if [[ -z "$RESP" ]]; then
RESP=$(curl -ksS --max-time 10 "$TARGET/" || true)
fi
VER=$(echo "$RESP" | grep -Eoi 'SimpleHelp[^0-9]{0,10}([0-9]+\.[0-9]+\.[0-9]+)' | grep -Eo '[0-9]+\.[0-9]+\.[0-9]+' | head -1)
if [[ -z "$VER" ]]; then
echo "UNKNOWN: could not parse SimpleHelp version from $TARGET" >&2
exit 3
fi
MAJ=$(echo "$VER" | cut -d. -f1)
MIN=$(echo "$VER" | cut -d. -f2)
PAT=$(echo "$VER" | cut -d. -f3)
# Vulnerable: <= 5.5.15 OR any 6.0 pre-release
# Patched: 5.5.16+ OR 6.0 RC2+
if (( MAJ < 5 )) || { (( MAJ == 5 )) && (( MIN < 5 )); }; then
echo "VULNERABLE: SimpleHelp $VER (predates 5.5.16 fix)"; exit 1
fi
if (( MAJ == 5 )) && (( MIN == 5 )) && (( PAT <= 15 )); then
echo "VULNERABLE: SimpleHelp $VER (<= 5.5.15)"; exit 1
fi
if (( MAJ == 6 )) && (( MIN == 0 )) && (( PAT == 0 )); then
echo "VULNERABLE: SimpleHelp 6.0 pre-release ($VER) — confirm RC2 or later out-of-band"; exit 1
fi
echo "PATCHED: SimpleHelp $VER"
exit 0
If you remember one thing.
Sources
What defenders are saying.
Crowdsourced verification outputs.
Results submitted by users who ran the verification payload against their environment.