← Back to Feed CACHED · 2026-10-19 00:55:14 · CACHE_KEY CVE-2026-96654
CVE-2026-96654 · CWE-84 · Disclosed 2026-09-23

Plex Media Server searchOne URL Injection Enabling Unauthenticated Plugin Function Invocation

ASSESSED — NOISGATE
Vendor
—
—
—
Reassessed
—
—
—
Verdict: —
Do you agree?
01 · The Real Story

The vendor stamped a MEDIUM sticker on the one rivet holding shut the door to unauthenticated remote code execution

CVE-2026-96654 is an improper URL neutralization flaw in the searchOne agent endpoint of Plex Media Server before 1.43.3.10861. The identifier parameter is spliced directly into an internal URL without encoding — a ? opens a query string, # truncates the path — letting an attacker forge requests to *any* plugin function on the loopback interface with arbitrary parameters. On its own, the bug requires loopback-origin access and yields plugin-function invocation (CWE-84, CVSS 6.5). All versions prior to 1.43.3.10861 are affected; Plex silently patched this in the 1.43.3 branch and began notifying users on September 1, 2026.

The vendor's MEDIUM 6.5 is defensible only if you evaluate this CVE in a vacuum. In reality, CVE-2026-96654 is Step 2 of the Plex2Shell chain (CVE-2026-96652 → -96654 → -96655 → -96656), a four-link unauthenticated RCE sequence with a combined CVSS 3.1 of 10.0. Researcher Zach Main published a weaponized PoC on October 16, 2026; honeypots recorded exploitation within 24 hours. Shodan shows ~586K internet-facing Plex instances, with over 36K confirmed unpatched as of September. Attackers are dropping XMRig miners and residential-proxy tools. Scoring this CVE at 6.5 while it's the authentication-bypass pivot that unlocks code execution on tens of thousands of reachable hosts is a textbook example of CVSS failing to capture chain context.

"MEDIUM alone, but the linchpin of an actively-exploited unauth RCE chain hitting 36K+ servers right now."
02 · The Attack Path

5 steps from start to impact.

STEP 01

Unauthenticated SSRF via Companion Protocol

The attacker sends a request to /player/timeline with X-Plex-Token: junk — the endpoint checks for *existence* of the header, not validity. The protocol parameter is injected with a loopback URL (e.g., http://127.0.0.1:32400/system/agents/...). When the subscription fires the unsubscribe callback, PMS issues a blind POST from its own socket to the attacker-controlled URL. This is CVE-2026-96652.
Conditions required:
  • Network reachability to port 32400
  • Plex Media Server < 1.43.3.10861
Where this breaks in practice:
  • Port 32400 must be internet-facing or attacker must be on the same network
  • Plex relay mode does NOT expose the raw port — only direct Remote Access does
Detection/coverage: Shodan dork product:Plex on port 32400 identifies exposed instances. The /identity endpoint leaks machineIdentifier and version without auth, enabling pre-attack version fingerprinting.
STEP 02

Loopback Pivot — Dead Auth Guard + searchOne Injection (THIS CVE)

The loopback POST from Step 1 hits /system/agents/*, which trusts loopback-origin requests unconditionally. The searchOne endpoint has a broken @lock decorator — it wraps validation logic but discards the return value when the identifier isn't recognized, so execution continues unauthenticated. The identifier parameter is spliced unsanitized into an internal URL: http://127.0.0.1:32400/:/plugins/%s/messaging/%s. Injecting ? opens a query string and # truncates the path, letting the attacker call any plugin function with arbitrary parameters. This is CVE-2026-96654.
Conditions required:
  • Step 1 SSRF delivers the loopback POST
  • Agent API trusts loopback origin (default behavior)
Where this breaks in practice:
  • If loopback trust were enforced with token validation, this step would fail
  • Requires the specific Python framework quirk in the @lock decorator
Detection/coverage: Application-layer logging of /system/agents requests with unusual identifier values containing ? or # characters would flag this step.
STEP 03

Admin Token Theft via sslip.io DNS Rebinding

The attacker uses the Step 2 injection to invoke GetResultFromNetwork in the bundled TheTVDB agent plugin. This function fetches arbitrary URLs. The Plex plugin framework auto-attaches the owner's admin X-Plex-Token to any outbound request whose URL starts with http://127.0.0.1. The attacker crafts http://127.0.0.1.<attacker-ip>.sslip.io — passes the prefix check but resolves to attacker infrastructure. The server sends its owner token to the attacker's listener. With this token, all admin endpoints (/:/prefs, /accounts) respond 200.
Conditions required:
  • Step 2 plugin injection succeeds
  • DNS resolution of sslip.io domains is not blocked
  • Outbound HTTP from Plex server is permitted
Where this breaks in practice:
  • Enterprises with DNS sinkholing or split-horizon DNS may block sslip.io resolution
  • Egress filtering blocking outbound HTTP from media servers would break this
Detection/coverage: DNS query logs showing *.sslip.io from Plex server hosts. Network IDS rules for X-Plex-Token header in outbound traffic to non-Plex destinations.
STEP 04

Malicious Codec Write via Transcoder Preference Abuse

With the stolen admin token, the attacker sets TranscoderH264Options to dump-yuv=<codec_dir>/x.so:qp=0 via PUT /:/prefs. They host a carrier video — an ELF shared object padded to fill a video frame, encoded as lossless H.264 — and trigger a transcode via /video/:/transcode/universal?path=http://attacker/item.xml. The server fetches the carrier, decodes it, and x264's dump-yuv option writes the decoded bytes (bit-exact due to qp=0) to the codec directory as a .so file. This combines CVE-2026-96655 (transcoder SSRF + file write).
Conditions required:
  • Valid admin token from Step 3
  • Transcoder binary present and functional
  • Codec directory is writable by the Plex service user
Where this breaks in practice:
  • Read-only filesystem or immutable container images would block the file write
  • AppArmor/SELinux profiles restricting Plex write paths could prevent codec dir writes
Detection/coverage: File integrity monitoring on the Plex Codecs directory. Process monitoring for Plex Transcoder spawning with unusual TranscoderH264Options values.
STEP 05

Code Execution via Unsigned Codec dlopen

On the next transcode invocation, avpriv_load_new_libs in the bundled libavutil.so.58 enumerates the codec set-directory and calls dlopen(RTLD_NOW) on every .so file. No signature verification, no allowlisting. The attacker's .so contains only a DT_INIT_ARRAY constructor — it executes on load before symbol resolution. The constructor forks and execs a reverse shell (or drops a miner/proxy). Code runs as uid=1000(plex) — the Plex service user. This is CVE-2026-96656.
Conditions required:
  • Malicious .so written to codec dir in Step 4
  • A second transcode job is triggered (attacker controls this)
Where this breaks in practice:
  • If Plex runs as a dedicated low-privilege user in a hardened container, blast radius is contained
  • seccomp profiles blocking dlopen or execve would prevent execution
Detection/coverage: EDR/auditd alerts on dlopen of unsigned .so files from the Codecs directory. Process tree anomalies: Plex Transcoder spawning shells, miners, or network tools.
03 · Compensating Control

1
HIGH 8.5→LOW 3.0
SEVERITY REDUCED
Block inbound access to port 32400 at the perimeter firewall immediately — The entire Plex2Shell chain requires network reachability to port 32400. Blocking this port at the firewall or security group eliminates the unauthenticated attack vector entirely. Plex's relay service (indirect streaming via Plex's cloud infrastructure) continues to work without direct port exposure. This is the single highest-leverage control. Deploy within 3 days per the noisgate mitigation SLA for HIGH-severity findings, though given active exploitation, hours is more appropriate.
2
HIGH 8.5→IGNORE 0.0
SEVERITY REDUCED
Update Plex Media Server to 1.43.3.10861 or later — The definitive fix. All four CVEs in the chain are patched in this release. Plex auto-update is available but not always enabled, especially on Docker and NAS deployments. Verify the running version via curl -s http://localhost:32400/identity | grep version. Deploy within 30 days per the noisgate remediation SLA for HIGH, but given active exploitation, treat this as an emergency patch — deploy within hours to days.
3
HIGH 8.5→MEDIUM 5.5
SEVERITY REDUCED
Block DNS resolution of *.sslip.io and similar DNS rebinding services from Plex hosts — Step 3 of the chain uses sslip.io to exfiltrate the admin token via DNS rebinding. Sinkholing *.sslip.io, *.nip.io, *.xip.io, and similar wildcard DNS services on your internal resolver breaks the token-theft step. This doesn't fix the underlying vulnerabilities but disrupts the specific published chain. Deploy within 3 days.
4
HIGH 8.5→MEDIUM 5.0
SEVERITY REDUCED
Restrict Plex service user write permissions and enable SELinux/AppArmor confinement — Step 4 requires writing a malicious .so to the Codecs directory. Restricting the Plex service user's write paths via mandatory access control (SELinux plex_t domain, AppArmor profile limiting writes to media directories only) prevents the file-write primitive. On Docker, use read-only root filesystem (--read-only) with explicit tmpfs mounts for required writable paths. Deploy within 30 days.
5
HIGH 8.5→HIGH 7.5
Deploy network-level IOC blocks for known attacker infrastructure — Block the following IPs at your perimeter: 45.194.92.222, 91.92.40.202, 176.65.139.228, 217.60.194.116. Monitor for DNS queries to proxystream.st and process names myawesomeproxy, mylovelyminer, x12345. This is a stopgap — attacker infrastructure rotates — but buys time. Deploy immediately.
What doesn't work
  • Plex authentication tokens (X-Plex-Token) — the chain's first step bypasses token validation entirely; the /player/timeline endpoint only checks for header *existence*, not validity. Having strong tokens does not help.
  • Reverse proxy with authentication in front of Plex — while this blocks direct access to port 32400, most Plex reverse-proxy guides pass through the /player/timeline and /system/agents paths unmodified. Unless the proxy explicitly blocks these endpoints, the chain still works.
  • Plex's built-in 'Require authentication for local network access' setting — the chain exploits loopback trust in the agent API, which is separate from Plex's user-facing authentication settings. This toggle does not affect loopback-origin request handling.
  • Network-level rate limiting — the exploit requires only a handful of HTTP requests (5-6 total across the chain). Rate limiting will not prevent exploitation.
04 · Intelligence Metadata

The supporting signals.

In-the-Wild ExploitationConfirmed active. Honeypot exploitation observed October 17, 2026 — within 24 hours of PoC release. Payloads include XMRig cryptominer and myawesomeproxy residential-proxy tool. Attacker IPs: 45.194.92.222, 91.92.40.202, 176.65.139.228. Payload source: 217.60.194.116.
Proof-of-ConceptPublic weaponized exploit. code-zm/plex2shell released October 16, 2026 by researcher Zach Main (zmain). Full four-CVE chain with automated exploitation. Requires Python 3.8+, ffmpeg, gcc.
EPSS0.00227 (0.227%), 12th percentile — misleadingly low given confirmed active exploitation. EPSS lags real-world activity here.
CISA KEVNot listed as of October 19, 2026. Given active exploitation, KEV inclusion is likely imminent. Plex is not a federal-agency staple, which may delay listing.
CVSS VectorCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:N — vendor scores *this CVE alone* at 6.5. The chained score (all four CVEs) is 10.0. The AV:N/PR:N/UI:N triplet correctly reflects that the full chain is unauthenticated and network-reachable.
Affected VersionsAll Plex Media Server versions before 1.43.3.10861 across all platforms (Linux, Windows, macOS, Docker, Synology, QNAP, FreeBSD). The underlying vulnerable code is in the Python plugin framework and bundled FFmpeg/x264 transcoder.
Fixed Version1.43.3.10861 (released ~September 1, 2026). Plex issued direct email notifications to affected users. No distro backports exist — Plex distributes its own binaries.
Internet ExposureShodan: ~586,217 internet-facing Plex instances (port 32400). ~36,000+ confirmed unpatched as of September 2026 scanning data. The /identity endpoint leaks version info without authentication, enabling mass triage by attackers.
Disclosure TimelineDisclosed 2026-09-23 (NVD). Plex began notifying users September 1, 2026. PoC dropped October 16. Exploitation observed October 17. 46-day window between notification and weaponization.
ResearcherZach Main (@code-zm, zmain.info). Notably used LLM-assisted iterative analysis for vulnerability discovery and chain construction.

Sources.

  1. Plex2Shell — Full Technical Writeup by Zach Main
  2. GitHub PoC: code-zm/plex2shell
  3. SecurityOnline: Plex2Shell Exploited in the Wild
  4. CordCutterNews: Plex Exploitation Advisory
  5. GitHub Advisory: GHSA-3j7c-jr86-m5jq
  6. SentinelOne Vulnerability Database: CVE-2026-96654
  7. Vulners / Rapid7: CVE-2026-96654
  8. OpenCVE: CVE-2026-96654
05 · The Call

Final Verdict
↑ UPGRADED to HIGH (8.5/10)

Why this verdict

  • Chain amplification is the dominant factor. CVE-2026-96654 alone is a loopback-only plugin injection (MEDIUM). But it is the *authentication-bypass pivot* in the Plex2Shell chain — without it, Steps 3-5 are unreachable. Evaluating it in isolation is like rating a detonator separately from the warhead. The chain it enables yields unauthenticated RCE (CVSS 10.0), and patching *this CVE alone* breaks the entire chain. Upgrade pressure: +2.0.
  • Active exploitation with commodity tooling. Weaponized PoC dropped October 16; honeypot compromise October 17. Attackers are running automated scans against 586K exposed instances. This is not theoretical — it is happening right now against your infrastructure if you run Plex. Upgrade pressure: +1.0.
  • Attack surface is massive and trivially enumerable. ~586K internet-facing Plex servers, ~36K confirmed unpatched. The /identity endpoint leaks exact version strings without authentication, so attackers can spray the exploit only at vulnerable targets. No guessing required. Upgrade pressure: +0.5.
  • Friction is low for internet-facing deployments. The chain requires zero authentication, zero user interaction, and works against default configurations. The only prerequisite is network reachability to port 32400, which Plex's own Remote Access feature encourages users to enable. Many home and small-business Plex admins have UPnP or manual port forwards active.
  • Role multiplier: Plex Media Server occupies low-to-typical enterprise roles. (a) *Low-value*: home media servers, dev machines — this is the vast majority of installs. Chain succeeds; blast radius is host-level (cryptominer, proxy abuse). (b) *Typical*: department media servers, digital signage hosts, NAS appliances on corporate networks — chain succeeds; blast radius is host + potential lateral movement pivot if the host has internal network access. (c) *High-value*: Plex is NOT canonically deployed as an IdP, DC, hypervisor, CI/CD, backup, or network-edge component. However, ~5-10% of installs may sit on Docker hosts or NAS devices that also host other services (file shares, databases). Compromise of these shared hosts could provide pivot access. This does not meet the ≥1% high-value-role threshold for a CRITICAL floor, but it reinforces HIGH.
  • Not CRITICAL because Plex is not a high-value-role component. Code execution is as uid=1000(plex), not root. The blast radius is host-level, not domain/fleet/supply-chain. Plex doesn't hold AD credentials, signing keys, or regulated data. The floor for CRITICAL requires the affected component to canonically occupy a high-value role (≥10% of installs), which Plex does not.

Why not higher?

The CRITICAL verdict requires that the affected component canonically occupies a high-value enterprise role where compromise yields domain takeover, fleet compromise, or supply-chain impact. Plex Media Server is a media streaming application — it does not manage identities, certificates, backups, hypervisors, or network perimeters. Code execution runs as a service user (not root), and the blast radius is confined to the host unless the attacker chains additional post-exploitation. While the exploitation is active and the chain is severe, the *impact ceiling* on most Plex deployments is cryptomining and proxy abuse, not organizational compromise.

Why not lower?

Active exploitation is confirmed and ongoing — this alone prevents any downgrade below HIGH. The chain is fully automated, requires zero authentication, and targets a surface of ~586K internet-facing hosts with ~36K confirmed vulnerable. The PoC-to-exploitation window was under 24 hours. Downgrading to MEDIUM would ignore that this CVE is the specific bypass that unlocks the entire RCE chain, and that attackers are actively leveraging it against real infrastructure right now. Every unpatched internet-facing Plex server is a live target.

06 · Verification

Crowdsourced verification payload.

Run this script on each host running Plex Media Server (Linux, macOS, Docker). It queries the local Plex /identity endpoint to extract the running version and compares it against the fixed version. Requires curl and network access to localhost:32400. No elevated privileges needed. Example: chmod +x check_plex.sh && ./check_plex.sh or for Docker: docker exec <plex_container> bash -c "$(cat check_plex.sh)"

noisgate-verify.sh
BASHREAD-ONLYSAFE
#!/usr/bin/env bash
# check_plex_cve_2026_96654.sh
# Checks whether the local Plex Media Server is vulnerable to
# CVE-2026-96654 (Plex2Shell chain, searchOne URL injection).
# Fixed in: 1.43.3.10861
# Exit codes: 1=VULNERABLE, 0=PATCHED, 2=UNKNOWN

set -euo pipefail

FIXED_VERSION="1.43.3.10861"
PLEX_URL="${PLEX_URL:-http://127.0.0.1:32400/identity}"

# Attempt to query the Plex identity endpoint
if ! RESPONSE=$(curl -sf --max-time 5 "$PLEX_URL" 2>/dev/null); then
  echo "UNKNOWN - Could not reach Plex at $PLEX_URL"
  echo "  Ensure Plex Media Server is running and accessible on localhost:32400"
  exit 2
fi

# Extract version from XML response
# Expected format: <MediaContainer ... version="1.43.3.10861" ...>
VERSION=$(echo "$RESPONSE" | grep -oP 'version="\K[^"]+' 2>/dev/null)

if [ -z "$VERSION" ]; then
  # Try alternate extraction for systems without -P flag
  VERSION=$(echo "$RESPONSE" | sed -n 's/.*version="\([^"]*\)".*/\1/p')
fi

if [ -z "$VERSION" ]; then
  echo "UNKNOWN - Could not parse Plex version from response"
  exit 2
fi

echo "Detected Plex Media Server version: $VERSION"
echo "Fixed version: $FIXED_VERSION"

# Version comparison function
# Returns 0 if $1 >= $2, 1 otherwise
version_gte() {
  local IFS='.'
  local i
  local -a v1=($1) v2=($2)
  for ((i=0; i<${#v2[@]}; i++)); do
    local a=${v1[i]:-0}
    local b=${v2[i]:-0}
    if (( a > b )); then return 0; fi
    if (( a < b )); then return 1; fi
  done
  return 0
}

if version_gte "$VERSION" "$FIXED_VERSION"; then
  echo "PATCHED - Plex $VERSION >= $FIXED_VERSION"
  echo "  CVE-2026-96654 (Plex2Shell chain) is remediated."
  exit 0
else
  echo "VULNERABLE - Plex $VERSION < $FIXED_VERSION"
  echo "  CVE-2026-96654 is exploitable. This host is part of the Plex2Shell"
  echo "  unauthenticated RCE chain (CVE-2026-96652/96654/96655/96656)."
  echo "  Active exploitation observed in the wild since October 17, 2026."
  echo "  ACTION: Update to $FIXED_VERSION+ immediately and check for IOCs:"
  echo "    - Unexpected .so files in Plex Codecs directory"
  echo "    - Processes: myawesomeproxy, mylovelyminer, xmrig"
  echo "    - Outbound connections to proxystream.st"
  exit 1
fi