The velvet rope at the nightclub checks that you're holding *a* ticket — it never reads what's printed on it
CVE-2026-96652 is a server-side request forgery in Plex Media Server's /player/timeline endpoint affecting all versions before 1.43.3.10861. The endpoint's authentication gate checks only that the X-Plex-Token HTTP header *exists* — sending X-Plex-Token: junk is enough to pass. The protocol parameter is then spliced raw into a callback URL with zero validation, letting any internet-reachable attacker coerce the Plex process into issuing HTTP POST requests to arbitrary destinations, including its own loopback interface. This single SSRF is the entry point for the Plex2Shell chain (CVE-2026-96652 → CVE-2026-96654 → CVE-2026-96655 → CVE-2026-96656), a four-stage sequence that escalates from unauthenticated SSRF to remote code execution as the Plex service user — with a weaponized PoC and active in-the-wild exploitation since October 17, 2026.
The vendor scored this CVE a 4.3 MEDIUM with PR:L (low privileges required). That rating is wrong on its face: the 'authentication' accepts any arbitrary string, which is functionally PR:N. Worse, the vendor score treats this SSRF in isolation, ignoring that it is the *only prerequisite* for a publicly weaponized, zero-click RCE chain scored CVSS 10.0 by the researcher. Plex notified users to update on September 1 and assigned CVEs on September 23, but provided no technical details — giving operators no way to gauge urgency. Researcher Zach Main published the full chain writeup and PoC on October 16; honeypots recorded live exploitation within 24 hours. Censys counts 360,000+ internet-facing Plex instances, and NAS-packaged builds (Synology, QNAP, Netgear) commonly lag the official release by days to weeks. The vendor MEDIUM label is dangerously understating the real-world risk profile.
5 steps from start to impact.
Unauthenticated SSRF via /player/timeline
/player/timeline on port 32400 with X-Plex-Token: anything and the protocol parameter set to a full loopback URL such as http://127.0.0.1:32400/system/agents/.... The endpoint's companion protocol unsubscribe handler fires a callback to the attacker-controlled URL. Because the Plex process originates this request, it arrives from 127.0.0.1, bypassing all loopback-only access controls. Weaponized in plex2shell by Zach Main.- Network access to Plex port 32400 (TCP)
- Any HTTP client — no valid credentials needed
- Plex instances behind a VPN or strict firewall are not reachable
- Instances with Remote Access disabled and no port-forward are unexposed
Loopback pivot via identifier injection (CVE-2026-96654)
/system/agents/*/searchOne API family is auth-free on loopback. A critical flaw in the @lock decorator discards its return value, so the authorization check never blocks execution. The identifier parameter is spliced into an internal URL template without encoding: http://127.0.0.1:32400/:/plugins/%s/messaging/%s. Injecting ? opens a query string and # truncates the trailing path, letting the attacker call *any* plugin function on the local plugin bus. Weaponized in plex2shell.- Step 1 SSRF lands on loopback successfully
- Plex plugin framework is running (default)
- None significant — default Plex install includes the plugin framework
/system/agents/ calls, but Plex's default logging level rarely captures request bodies.Admin token theft via DNS prefix confusion (CVE-2026-96655)
GetResultFromNetwork plugin function, which fetches remote URLs. Plex's plugin framework automatically attaches the server owner's X-Plex-Token to any request whose URL starts with http://127.0.0.1 — but uses an unbounded prefix match. The URL http://127.0.0.1.attacker.sslip.io passes the check while DNS-resolving to the attacker's server. The Plex process sends the owner's admin token directly to the attacker. Weaponized in plex2shell.- Step 2 pivot to plugin bus succeeds
- Attacker controls a DNS record (sslip.io or equivalent)
- Target Plex can resolve external DNS and reach the internet
- Environments with DNS filtering or egress restrictions may block the sslip.io resolution
- Air-gapped or heavily segmented Plex hosts cannot call back
127.0.0.1.* patterns or outbound HTTP from the Plex process to unexpected external hosts.Transcoder file write via codec directory hijack (CVE-2026-96656)
TranscoderH264Options preference to include dump-yuv=/path/to/Codecs/malicious.so:qp=0. This abuses an x264 encoder debug option that writes decoded YUV frames to a file path — with lossless encoding (qp=0), the output is a bit-exact copy of the input. The attacker hosts a specially crafted H.264 video whose decoded frame bytes form a valid ELF shared-object binary, then triggers a transcode via /video/:/transcode/universal. The Plex transcoder writes the attacker's .so into the Codecs directory. Weaponized in plex2shell.- Step 3 token theft succeeds
- Attacker can host a crafted H.264 payload reachable from the target
- Plex Codecs directory is writable by the service user (default)
- Read-only filesystem or hardened container mounts on the Codecs dir would block the write
- AppArmor/SELinux profiles restricting write paths for the Plex process (non-default)
/var/lib/plexmediaserver/Library/Application Support/Plex Media Server/Codecs/) for unexpected .so files.Code execution via unsigned codec loading
avpriv_load_new_libs in bundled libavutil.so.58 enumerates the Codecs directory and calls dlopen(RTLD_NOW) on every .so file it finds. There is no signature verification, no filename prefix check, and no execute-bit requirement. ELF constructors (DT_INIT_ARRAY) fire during dlopen before symbol resolution, executing attacker code as the Plex service user (typically uid=1000 or plex). The public PoC forks a reverse shell. Weaponized in plex2shell; observed in the wild deploying XMRig miner and myawesomeproxy.- Step 4 file write to Codecs directory succeeds
- A subsequent transcode job is triggered (attacker-initiated)
- If the Codecs directory was made read-only, no .so is written
- Endpoint protection that flags dlopen of newly-written .so files in non-standard paths
/bin/sh, curl, wget, xmrig). Process tree monitoring is the highest-fidelity detection.chmod 555 or mount with ro) blocks step 4 of the chain — the transcoder cannot write the malicious .so file. This breaks the RCE stage even if the SSRF and token theft succeed. Note: this may break legitimate codec downloads; test in a staging instance first. Deploy within 3 days per noisgate mitigation SLA.127.0.0.1.attacker.sslip.io to exfiltrate the admin token. Blocking wildcard DNS services (sslip.io, nip.io, xip.io) and suspicious outbound HTTP from the Plex process degrades the token-theft stage. This is a partial mitigation — a determined attacker can use their own DNS infrastructure. Deploy within 3 days./bin/sh, /bin/bash, cmd.exe), crypto miners (xmrig), or network tools (curl, wget, nc) will catch post-exploitation activity. This is detection, not prevention — it does not stop the chain but enables rapid incident response. Configure within 3 days.- Rotating X-Plex-Token values — the SSRF bypass accepts *any* string as a token; the attacker never needs a valid token to initiate the chain. Rotation protects nothing.
- Web Application Firewall (WAF) rules on /player/timeline — the request uses legitimate-looking parameters with no obvious malicious signatures. The SSRF payload is a well-formed URL in the
protocolfield. WAF string-matching is trivially evaded. - Disabling Plex Remote Access in settings — this only removes UPnP/NAT-PMP auto-forwarding. If the operator previously configured a manual port-forward or the host is otherwise internet-facing, disabling Remote Access in Plex does not close the port. You must verify at the firewall level.
- Network-level IDS signatures for the PoC — the initial SSRF request is a standard HTTP GET with normal-looking headers. The exploit does not use shellcode, encoded payloads, or protocol anomalies in the initial request. Signature-based detection at the network layer will miss step 1.
The supporting signals.
| In-the-wild exploitation | CONFIRMED. Honeypot exploitation observed October 17, 2026 — 24 hours after PoC release. Attacker IPs: 45.194.92.222, 91.92.40.202, 176.65.139.228. Payloads hosted at 217.60.194.116. Delivered XMRig cryptominer and myawesomeproxy (traffic-routing backdoor). Source: boredhackerblog. |
|---|---|
| Proof-of-concept | PUBLIC + WEAPONIZED. Full chain PoC: code-zm/plex2shell released October 16, 2026 by Zach Main (@zm_0x). Automates all four CVEs from unauth SSRF to reverse shell. Requires Python 3.8+, ffmpeg, and compiler tools. Not yet indexed on pocindex.io at time of review, but the GitHub repo is the canonical PoC. |
| EPSS | 0.00222 (≈ 80th percentile). EPSS has not yet caught up with the active exploitation; expect a significant jump in the next model update. Treat this score as stale. |
| CISA KEV | Not listed as of 2026-10-19. Given confirmed in-the-wild exploitation, KEV addition is likely imminent. Do not wait for KEV listing to act. |
| CVSS vector (vendor) | CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:N → 4.3 MEDIUM. The PR:L is factually incorrect — the token check accepts any junk value. Corrected to PR:N the base score becomes 5.3. Neither score reflects the chain context. |
| CVSS vector (chain) | CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H → 10.0 CRITICAL (researcher-assessed for the Plex2Shell chain). This is the real-world impact vector. |
| Affected versions | Plex Media Server < 1.43.3.10861 across all platforms: Linux, Windows, macOS, FreeBSD, Synology, QNAP, Netgear, WD, Docker. NAS-packaged builds from Synology and QNAP may still lag behind the official 1.43.3 release due to vendor app-store approval delays. |
| Fixed version | 1.43.3.10861 (released September 1, 2026 via Plex update channel). NAS users: check your vendor's package manager; if unavailable, download manually from Plex and sideload. |
| Internet exposure | Censys: 428,083 Plex instances internet-facing. Shodan: 295,694 on port 32400. Earlier September 2026 scan found 36,000+ unpatched instances. Plex's Remote Access feature is enabled by default and instructs users to port-forward 32400 — this is the product's normal operating posture. |
| Researcher & timeline | Discovered by Zach Main (zmain.info). Reported July 27, 2026. Acknowledged + bounty paid August 4 ($500). Plex pushed silent update September 1. CVEs assigned September 23. Full writeup + PoC published October 16. In-the-wild exploitation October 17. |
Sources.
- Plex2Shell — Full Technical Writeup (Zach Main)
- plex2shell PoC — GitHub (code-zm)
- Plex2Shell Exploited in the Wild — SecurityOnline
- Plex Media Server Exploitation — CordCuttersNews
- CVE-2026-96652 — SentinelOne Vulnerability Database
- Plex Security Update Analysis — ETTAYEB
- Plex Media Server 1.43.3 Security Update — NAS Compares
- CVE-2026-96652 — OpenCVE
Why this verdict
- Broken authentication eliminates the PR:L barrier. The vendor CVSS assumes low-privilege authentication (
PR:L), but the/player/timelineendpoint accepts literally any string asX-Plex-Token. This isPR:Nin practice — no credentials, no account, no brute-force. The vendor's 4.3 baseline is built on a false premise. - Weaponized chain converts SSRF into unauthenticated RCE. CVE-2026-96652 alone is a limited SSRF, but it is the sole external-facing prerequisite for the Plex2Shell chain (CVE-2026-96652 → 96654 → 96655 → 96656). The chain is fully automated in a public PoC, scores CVSS 10.0, and achieves code execution as the Plex service user with zero user interaction. Patching this single CVE breaks the entire chain at step 1.
- Active exploitation confirmed within 24 hours of PoC. Honeypots recorded chain exploitation on October 17, 2026 — one day after public PoC. Payloads include XMRig miner and a proxy backdoor. Three attacker IPs identified. This is not theoretical risk; it is an ongoing campaign.
- Massive internet-facing attack surface by design. Plex's Remote Access feature encourages port-forwarding 32400 to the internet. Censys identifies 428,000+ exposed instances. Even after Plex's September 1 update push, 36,000+ instances were confirmed unpatched. NAS-packaged builds (Synology, QNAP) lag official patches by days to weeks, extending the vulnerable window for a large segment of the install base.
- Role multiplier: home NAS and media servers. Plex is not canonically a high-value-role component (it is media software, not identity infrastructure or a hypervisor). The *typical* deployment is a home NAS or dedicated media server. However: (1) NAS devices frequently store personal documents, financial records, and backups alongside media — RCE means full data access. (2) Home and SMB Plex hosts often sit on flat networks with no segmentation, enabling lateral movement to other devices. (3) At 360K+ exposed instances, mass exploitation at scale creates a significant botnet and proxy network — already demonstrated by the myawesomeproxy payload. (4) A subset of Plex instances run on cloud VMs colocated with production workloads in the same VPC. The blast radius is host-level per instance but fleet-scale in aggregate. This does not trigger the canonical high-value-role CRITICAL floor, but the combination of active exploitation, zero authentication, massive surface, and demonstrated mass-compromise campaigns independently warrants CRITICAL.
- No friction survives contact with reality. The entire chain requires only network access to port 32400 and outbound DNS/HTTP from the target — both are the *default operating posture* of Plex. No user interaction, no valid credentials, no special configuration, no race condition. Every step has zero or near-zero friction in a standard Plex deployment.
Why not higher?
A 10.0 would be appropriate for the *chain* as a unit, but we are assessing CVE-2026-96652 individually. The SSRF alone does not achieve RCE — it requires three additional vulnerabilities (CVE-2026-96654, -96655, -96656) to complete the chain. If any of those companion CVEs were independently patched or mitigated, this SSRF reverts to a moderate-impact information-gathering primitive. We score 9.0 to reflect that the chain is public, weaponized, and actively exploited, while acknowledging the technical dependency on the companion bugs.
Why not lower?
Downgrading below CRITICAL is indefensible given three simultaneous conditions: (1) the authentication gate is functionally non-existent, (2) a weaponized public PoC automates the full chain to RCE, and (3) active in-the-wild exploitation is confirmed and ongoing. The 'requires authentication' argument that might justify MEDIUM or HIGH is factually false — X-Plex-Token: junk passes. The 'SSRF alone is limited impact' argument ignores that the companion chain bugs are *also* unpatched on every vulnerable instance; they are not independent mitigations. Any defender treating this as MEDIUM per the vendor label is leaving an actively-exploited unauthenticated RCE chain open on their network.
Crowdsourced verification payload.
Run this script on the Plex host itself or from any machine that can reach the Plex server's HTTP interface. No authentication is required — the /identity endpoint is unauthenticated by design. Invoke with: bash check_cve_2026_96652.sh http://your-plex-host:32400 (defaults to http://127.0.0.1:32400 if no argument is given). No elevated privileges needed.
#!/usr/bin/env bash
# noisgate — CVE-2026-96652 Plex Media Server SSRF (Plex2Shell entry point)
# Checks installed version against fixed version 1.43.3.10861
# Exit codes: 0=PATCHED, 1=VULNERABLE, 2=UNKNOWN
set -uo pipefail
FIXED="1.43.3.10861"
TARGET="${1:-http://127.0.0.1:32400}"
version_gte() {
# Returns 0 (true) if $1 >= $2 via sort -V
[ "$(printf '%s\n%s' "$1" "$2" | sort -V | head -n1)" = "$2" ]
}
echo "[*] noisgate CVE-2026-96652 checker"
echo "[*] Target : ${TARGET}"
echo "[*] Fixed : >= ${FIXED}"
echo ""
# /identity is unauthenticated and returns server version in XML
RESPONSE=$(curl -sf --connect-timeout 5 --max-time 10 "${TARGET}/identity" 2>/dev/null)
RC=$?
if [ $RC -ne 0 ] || [ -z "$RESPONSE" ]; then
echo "UNKNOWN — could not reach ${TARGET}/identity (curl exit $RC)"
echo "Verify Plex Media Server is running and the URL is correct."
exit 2
fi
# Parse version from XML: <MediaContainer ... version="1.x.y.z" ...>
VERSION=$(echo "$RESPONSE" | sed -n 's/.*version="\([^"]*\)".*/\1/p' | head -n1)
if [ -z "$VERSION" ]; then
echo "UNKNOWN — /identity responded but version not parseable"
echo "Raw (first 300 chars): ${RESPONSE:0:300}"
exit 2
fi
echo "[*] Detected: ${VERSION}"
echo ""
if version_gte "$VERSION" "$FIXED"; then
echo "PATCHED — Plex Media Server ${VERSION} >= ${FIXED}"
exit 0
else
echo "VULNERABLE — Plex Media Server ${VERSION} < ${FIXED}"
echo ""
echo " CVE : CVE-2026-96652 (SSRF in /player/timeline)"
echo " Chain : Plex2Shell → unauthenticated RCE"
echo " Exploited : IN THE WILD since 2026-10-17"
echo " Fix : Update to >= ${FIXED} IMMEDIATELY"
exit 1
fi