Skip to content

Repository files navigation

CVE-2026-35031: Jellyfin Subtitle Upload Path Traversal to RCE

CVE-ID CVSS Score CWE Affected Product Status

TL;DR

A critical path traversal vulnerability in Jellyfin Media Server allows authenticated users with "Upload Subtitles" permission to upload files to arbitrary locations on disk. By exploiting the unvalidated Format field in the subtitle upload endpoint, attackers can write files to sensitive locations, extract sensitive data, escalate privileges, and ultimately execute arbitrary code as root via LD_PRELOAD injection.

  • CVSS Score: 9.9 (Critical)
  • Affected Versions: Jellyfin < 10.11.7
  • Fixed Version: Jellyfin 10.11.7+
  • Authentication Required: Yes (non-admin user with subtitle upload permission)
  • Remote Code Execution: Yes, as root
  • Exploit Complexity: Low

Table of Contents

  1. Quick Facts
  2. What is Jellyfin?
  3. Vulnerability Deep Dive
  4. Impact Analysis
  5. Affected Versions
  6. Detection
  7. Indicators of Compromise
  8. Remediation
  9. References
  10. Author

Quick Facts

Property Value
CVE ID CVE-2026-35031
CVSS Score 9.9 (Critical)
CWE CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')
Affected Product Jellyfin Media Server
Affected Versions < 10.11.7
Fixed Version 10.11.7 and later
Vulnerability Type Path Traversal + Arbitrary File Write + RCE
Authentication Required Yes (non-admin user)
Privileges Required "Upload Subtitles" permission
Default Port 8096/TCP
GitHub Advisory GHSA-9p5f-5x8v-x65m
Patch Status Available and released
Exploit Public Yes

What is Jellyfin?

Jellyfin is a free and open-source media server designed to help you manage and stream your personal media collection. It provides functionality similar to commercial media servers but with full source code transparency and community control.

Key Features

  • Self-hosted media streaming (music, movies, TV shows)
  • Multi-user support with granular permission controls
  • Subtitle management and synchronization
  • Web-based interface accessible via HTTP/HTTPS
  • Cross-platform deployment (Linux, Windows, macOS)
  • Support for various media formats and streaming protocols

Network Architecture

                          Jellyfin Media Server (Port 8096)
                         /                |                \
                        /                 |                 \
                   Web UI            REST API          Media Streams
                  (Browser)        (Authenticated)    (Subtitle Upload)
                                         |
                        /System/Info/Public (unauthenticated)
                        /Videos/{itemId}/Subtitles (vulnerable)
                        /Library/Collections (admin)

Client Devices > Network > Jellyfin Server > Database + Storage
                                  |
                            /var/lib/jellyfin/
                            /etc/ld.so.preload (writable via vulnerability)

Vulnerability Deep Dive

Root Cause Analysis

The vulnerability exists in the subtitle upload endpoint (/Videos/{itemId}/Subtitles) which accepts file uploads and stores them on disk. The critical flaw lies in the insufficient validation of the Format field parameter.

Vulnerable Code Pattern

The endpoint processes subtitle uploads without properly validating or sanitizing the Format field:

POST /Videos/{itemId}/Subtitles HTTP/1.1
Content-Type: multipart/form-data

[Binary subtitle data]
Format: /../../../etc/ld.so.preload
Language: en

The Format parameter is intended to specify subtitle format (srt, vtt, ass, etc.) but instead gets treated as part of the file path:

Base Path: /var/lib/jellyfin/subtitles/
User Input: /../../../etc/ld.so.preload
Result:    /var/lib/jellyfin/subtitles/../../../etc/ld.so.preload
Resolved:  /etc/ld.so.preload (via path traversal)

Attack Chain Breakdown

The vulnerability chains together multiple weaknesses to achieve remote code execution as root:

Step 1: Subtitle Upload with Path Traversal
        POST /Videos/{itemId}/Subtitles
        Format: /../../../etc/ld.so.preload
                    |
                    v
Step 2: Arbitrary File Write
        Write attacker-controlled data to /etc/ld.so.preload
                    |
                    v
Step 3: File Read via .strm Files
        Create .strm files pointing to sensitive paths
        Extract database contents and credentials
                    |
                    v
Step 4: Database Extraction
        Access /jellyfin/jellyfin.db via .strm
        Extract admin user hashes
                    |
                    v
Step 5: Admin Privilege Escalation
        Reset admin password or create new admin account
                    |
                    v
Step 6: RCE via LD_PRELOAD Injection
        LD_PRELOAD=/path/to/malicious.so java
        Arbitrary code execution as root

Path Traversal Mechanism

Input Validation Failure:

Format Field Validation:
  Expected: srt | vtt | ass | ssa | sub | subrip
  Actual:   /../../../etc/ld.so.preload
  Result:   NO VALIDATION > PATH TRAVERSAL ALLOWED

File Write Operation:
  String Concatenation: "/subtitles/" + user_format + ".srt"
                        |
  NO CANONICALIZATION:  Path component not resolved before write
  NO WHITELIST:         Format values not restricted
  NO BOUNDS CHECK:      ".." sequences not filtered
                        |
                        v
  Final Path:           /etc/ld.so.preload (EXPLOITED)

LD_PRELOAD Exploitation

The LD_PRELOAD technique is a powerful privilege escalation and code execution method on Linux systems:

LD_PRELOAD Injection Flow:

1. Attacker writes malicious .so (shared object) to /etc/ld.so.preload
   
   /etc/ld.so.preload contents:
   /path/to/attacker.so

2. Java process starts (Jellyfin runs on Java):
   
   kernel > execve("java", ...) > glibc initialization
                                     |
                                     v
                          Check /etc/ld.so.preload
                                     |
                                     v
                          Load attacker.so FIRST
                                     |
                                     v
                          Execute attacker code
                          (BEFORE Java main())

3. Code Execution Context:
   
   Process Owner:   root (Jellyfin typically runs as root)
   Permissions:     Full system access
   Timing:          Before application initialization
   Detection:       Minimal (malicious code runs early)

4. Attacker Capabilities:
   
   > Create reverse shell with full root privileges
   > Extract sensitive data before application starts
   > Modify Java application behavior
   > Persist via cron jobs or systemd services
   > Establish C2 communication

Why LD_PRELOAD Works as Escalation

User Level Access > Path Traversal > Write /etc/ld.so.preload
  |
  v (Next process execution)
  |
Kernel reads /etc/ld.so.preload > Loads attacker .so
  |
  v
Malicious code executes in root context
  |
  v
Full system compromise

Impact Analysis

Confidentiality

CRITICAL - Complete information disclosure

  • Database extraction: admin credentials, user passwords, API keys
  • Subtitle files and media metadata exposure
  • Configuration file access with sensitive data
  • System information gathering for further exploitation

Integrity

CRITICAL - System-wide file modification

  • Arbitrary file write to any location on disk
  • Application binary modification
  • System configuration tampering
  • Database corruption or manipulation

Availability

CRITICAL - Service disruption and denial

  • System shutdown or crash via malicious .so in LD_PRELOAD
  • Disk space exhaustion through large file writes
  • Process killing or resource starvation
  • Complete service unavailability

Affected Components

  • Jellyfin Media Server process (running as root in most deployments)
  • Operating system kernel and libraries
  • Stored media and metadata
  • User authentication systems
  • System-wide processes linked against glibc

Business Impact

  • Data Breach: All stored credentials and user data compromised
  • Service Outage: Jellyfin and potentially other services become unavailable
  • Lateral Movement: Compromised system becomes pivot point for network attacks
  • Compliance Violation: GDPR, CCPA, HIPAA violations if PII exposed
  • Supply Chain Risk: If Jellyfin serves shared or enterprise media

Affected Versions

Version Status Notes
< 10.8.0 Vulnerable Original vulnerability present
10.8.0 - 10.11.6 Vulnerable Path traversal and RCE possible
10.11.7+ Patched Format field properly validated
10.12.0+ Patched Latest version with security fixes

Version Detection

The vulnerability can be detected by checking the version string from the /System/Info/Public endpoint:

GET /System/Info/Public HTTP/1.1
Host: jellyfin-server:8096

Response:
{
  "ServerName": "MyJellyfin",
  "Version": "10.10.3",  < Vulnerable
  "ProductName": "Jellyfin",
  "StartupWizardCompleted": true
}

Detection

Python Scanner

The CVE-2026-35031_Jellyfin_RCE_detector.py script provides automated vulnerability detection.

Installation and Requirements

pip install requests urllib3

Usage

python CVE-2026-35031_Jellyfin_RCE_detector.py -t 10.0.0.5:8096
python CVE-2026-35031_Jellyfin_RCE_detector.py -t http://10.0.0.0/24
python CVE-2026-35031_Jellyfin_RCE_detector.py -t targets.txt -o results.json

Command Line Options

-t, --target HOST[:PORT] or CIDR or FILE
                       Single target, IP range, or file with targets
-p, --port PORT        Custom port (default: 8096)
--timeout SECONDS      Connection timeout (default: 10)
-o, --output FILE      Save results to JSON file
-v, --verbose          Enable verbose logging
--no-ssl-verify        Disable SSL certificate verification

Example Output

[*] CVE-2026-35031 Jellyfin RCE Detection Scanner
[*] Target: http://10.0.0.5:8096
[*] Scan Time: 2026-04-15T12:00:00Z
[*] Detection method: /System/Info/Public version check
[*] Vulnerable: Jellyfin < 10.11.7

======================================================================
Target: http://10.0.0.5:8096
Scan Time: 2026-04-15T12:00:00Z
Risk Level: CRITICAL
======================================================================
  Is Jellyfin:           YES
  Jellyfin Version:      10.10.3
  Server Name:           MediaServer
  Operating System:      Linux
  Subtitle Endpoint:     Accessible
  Vulnerable:            YES

  *** VULNERABLE: Path traversal in subtitle upload ***
  *** Chains to arbitrary file write and RCE as root via ld.so.preload ***
  *** Upgrade to Jellyfin 10.11.7 immediately ***

======================================================================
Summary:
  Total Targets: 1
  Vulnerable: 1
  Patched: 0
  Unknown: 0
======================================================================

Detection Logic

The scanner performs the following checks:

  1. Service Detection: Connects to target port and checks HTTP headers
  2. Jellyfin Verification: Queries /System/Info/Public endpoint
  3. Version Extraction: Parses Version field from JSON response
  4. Vulnerability Assessment: Compares version against patch version (10.11.7)
  5. Endpoint Verification: Confirms subtitle upload endpoint exists
  6. Risk Calculation: Determines CVSS impact based on version

Nmap NSE Script

The CVE-2026-35031_Jellyfin_RCE.nse script provides integration with Nmap for vulnerability scanning.

Installation

# Copy to Nmap scripts directory
sudo cp CVE-2026-35031_Jellyfin_RCE.nse /usr/share/nmap/scripts/

# Update Nmap database
sudo nmap --script-updatedb

Usage

# Basic scan
nmap -p 8096 --script CVE-2026-35031_Jellyfin_RCE 10.0.0.5

# Comprehensive scan with service detection
nmap -sV -p 8096 --script CVE-2026-35031_Jellyfin_RCE 10.0.0.5

# Scan entire subnet
nmap -sV -p 8096 --script CVE-2026-35031_Jellyfin_RCE 10.0.0.0/24

# Aggressive scanning with timing
nmap -sV -p- --script CVE-2026-35031_Jellyfin_RCE -T4 10.0.0.5

# Export results to XML
nmap -sV -p 8096 --script CVE-2026-35031_Jellyfin_RCE -oX results.xml 10.0.0.5

Example Output

PORT     STATE SERVICE VERSION
8096/tcp open  http    Jellyfin Media Server 10.10.3
| CVE-2026-35031_Jellyfin_RCE:
|   VULNERABLE:
|   Jellyfin Subtitle Path Traversal to RCE (CVE-2026-35031)
|     State: VULNERABLE
|     Risk level: CRITICAL
|     CVSS Score: 9.9
|     Jellyfin Version: 10.10.3
|     Fixed Version: 10.11.7
|     Description:
|       Jellyfin 10.10.3 is vulnerable to CVE-2026-35031. The subtitle
|       upload endpoint (/Videos/{itemId}/Subtitles) does not validate
|       the Format field, allowing path traversal and arbitrary file write.
|       This chains into remote code execution as root via LD_PRELOAD.
|     Vulnerability Chain:
|       1. POST /Videos/{itemId}/Subtitles with Format=/../../../etc/ld.so.preload
|       2. Arbitrary file write to /etc/ld.so.preload
|       3. Database extraction via .strm files
|       4. Admin privilege escalation
|       5. RCE as root via LD_PRELOAD injection
|     Affected Endpoint: /Videos/{itemId}/Subtitles
|     Authentication Required: YES (non-admin user)
|     References:
|       https://nvd.nist.gov/vuln/detail/CVE-2026-35031
|       https://github.com/jellyfin/jellyfin/security/advisories/GHSA-9p5f-5x8v-x65m
|_      https://github.com/jellyfin/jellyfin/releases/tag/v10.11.7

Script Parameters

# Custom timeout for slow networks
nmap --script CVE-2026-35031_Jellyfin_RCE --script-args timeout=30 10.0.0.5

# Debug mode for troubleshooting
nmap --script CVE-2026-35031_Jellyfin_RCE -d 10.0.0.5

# Aggressive version detection
nmap -sV --version-intensity 9 --script CVE-2026-35031_Jellyfin_RCE 10.0.0.5

Indicators of Compromise

Log Indicators

Jellyfin Server Logs (/var/log/jellyfin/jellyfin.log)

[ERR] Error processing subtitle upload: Invalid path characters detected
[ERR] Exception in subtitle handling: DirectoryNotFoundException
[ERR] Unauthorized file system access attempt
[WARN] Unusual subtitle format detected: /../../../
[ERR] Security violation: Path traversal attempt blocked

System Logs (/var/log/syslog or /var/log/messages)

subtitle upload process: segmentation fault (core dumped)
kernel: [security] Attempted to load from LD_PRELOAD: /etc/ld.so.preload
ld.so.preload: permission denied or file corrupted
Java process crashed after LD_PRELOAD initialization
Unexpected behavior from root-level Java process

File System Indicators

Modified System Files

/etc/ld.so.preload          - Should not contain any paths if not configured
/lib/x86_64-linux-gnu/      - Look for suspicious .so files created recently
/var/lib/jellyfin/subtitles - Check for files outside normal naming
/etc/passwd                 - Verify no unauthorized access or modification
/var/lib/jellyfin/db        - Database timestamps may indicate extraction

Suspicious File Paths in Subtitle Directory

/../../../etc/ld.so.preload
/../../../root/.ssh/authorized_keys
/../../../var/lib/jellyfin/jellyfin.db
../../../proc/self/environ

Network Indicators

Suspicious HTTP Requests

POST /Videos/[0-9]+/Subtitles
  - Format parameter contains: /.. or ..\ patterns
  - Format parameter contains absolute paths starting with /
  - Format parameter does not match known subtitle formats

Encoded Payloads:
  %2e%2e%2f   (URL encoded ../)
  ..%252f      (Double encoded ../)
  ....//       (Bypass patterns)

Outbound Connections from Jellyfin Process

Reverse shells to external IPs
Connections to known C2 infrastructure
DNS requests to anomalous domains
Sudden spike in network traffic after failed subtitle upload

Process Indicators

Jellyfin Process Anomalies

java process executing system commands
java process spawning shell processes (/bin/bash, /bin/sh)
java process opening connections to unusual ports
java process reading system files like /etc/shadow
Unusual CPU or memory usage spikes
Child processes with different UID than parent

Database Indicators

Jellyfin Database Changes (jellyfin.db)

New admin user created outside normal workflow
Admin password changed without admin action
API keys/tokens created unexpectedly
Unusual activity in audit logs

Remediation

Immediate Actions (Priority: CRITICAL)

  1. Upgrade Jellyfin Immediately

    # Docker deployment
    docker pull jellyfin/jellyfin:latest
    docker-compose down
    docker-compose up -d
    
    # Package manager (Ubuntu/Debian)
    sudo apt-get update
    sudo apt-get install --only-upgrade jellyfin
    
    # Package manager (Fedora/RHEL)
    sudo dnf upgrade jellyfin
  2. Stop Jellyfin Service

    sudo systemctl stop jellyfin
  3. Check for Exploitation

    # Check if ld.so.preload was modified
    ls -la /etc/ld.so.preload
    cat /etc/ld.so.preload
    
    # Check subtitle directory for suspicious files
    find /var/lib/jellyfin/subtitles -type f -newer /proc -ls
    
    # Check Jellyfin data directory
    find /var/lib/jellyfin -type f -newermt "2026-04-14" -ls

Short-term Mitigations (Priority: HIGH)

  1. Restrict Subtitle Upload Permission

    Jellyfin Web UI > Settings > Users
    Disable "Upload Subtitles" for all non-admin users
    Review all users with this permission
    
  2. Network Segmentation

    # Only allow trusted networks to access Jellyfin
    sudo ufw allow from 192.168.1.0/24 to any port 8096
    sudo ufw deny from any to any port 8096
    
  3. File System Permissions

    # Ensure Jellyfin runs with minimal privileges
    sudo usermod -s /usr/sbin/nologin jellyfin
    
    # Restrict ld.so.preload permissions
    sudo chmod 644 /etc/ld.so.preload
    sudo chmod 644 /etc/ld.so.conf
    
    # Set proper permissions on Jellyfin directory
    sudo chown -R jellyfin:jellyfin /var/lib/jellyfin
    sudo chmod 750 /var/lib/jellyfin
  4. Monitor for Exploitation Attempts

    # Watch subtitle upload endpoint logs
    tail -f /var/log/jellyfin/jellyfin.log | grep -i subtitle
    
    # Monitor system logs for ld.so.preload changes
    auditctl -w /etc/ld.so.preload -p wa -k ld_preload_changes

Long-term Hardening (Priority: MEDIUM)

  1. Implement Web Application Firewall (WAF)

    Block requests containing:
    - Path traversal patterns: ../ ..\ ..\
    - Suspicious file paths: /etc/ /root/ /proc/
    - Encoded variations: %2e%2e%2f
    
  2. Enable Security Module

    # AppArmor (Ubuntu/Debian)
    sudo aa-enforce /etc/apparmor.d/usr.bin.java
    
    # SELinux (Fedora/RHEL)
    sudo semanage fcontext -a -t jellyfin_home_t "/var/lib/jellyfin(/.*)?"
    sudo restorecon -R /var/lib/jellyfin
  3. Run Jellyfin as Non-root User

    # Create dedicated user if not exists
    sudo useradd -r -s /usr/sbin/nologin jellyfin
    
    # Update systemd service
    sudo sed -i 's/User=.*/User=jellyfin/' /etc/systemd/system/jellyfin.service
    sudo systemctl daemon-reload
    sudo systemctl restart jellyfin
  4. Implement Regular Backups

    # Automated daily backups
    sudo crontab -e
    # 0 2 * * * /usr/local/bin/jellyfin-backup.sh
    
    # Verify backup integrity
    tar -tzf /backup/jellyfin-$(date +%Y%m%d).tar.gz > /dev/null
  5. Enable Audit Logging

    # Log all file access to sensitive locations
    auditctl -w /etc/ld.so.preload -p wa -k ld_preload_audit
    auditctl -w /var/lib/jellyfin -p wa -k jellyfin_audit
    
    # Monitor process execution from Jellyfin
    auditctl -a always,exit -F exe=/usr/bin/java -F arch=b64 -S execve -k jellyfin_exec

Verification Steps

# 1. Verify Jellyfin version after upgrade
curl -s http://localhost:8096/System/Info/Public | jq .Version

# 2. Confirm no unauthorized ld.so.preload entries
cat /etc/ld.so.preload | wc -l  # Should be 0 or contain only legitimate entries

# 3. Check Jellyfin process permissions
ps aux | grep jellyfin | grep -v grep

# 4. Verify subnet connectivity restrictions
sudo ufw status

# 5. Test subtitle upload with non-admin user (should work normally)
# Try uploading a legitimate .srt file and confirm it's stored correctly

References

Official Sources

Related Vulnerabilities & Research

Security Tools & Resources


Author

Vulnerability Discovered & Documented By:

Kerem Oruc (@keraattin)

Contribution

If you have improvements to this documentation or detection tools, please submit a pull request or open an issue.


Disclaimer: This document is for educational and authorized security testing purposes only. Unauthorized access to computer systems is illegal. Always obtain proper authorization before conducting security assessments.

Last Updated: 2026-04-15 | Status: PUBLISHED

About

Critical path traversal to RCE vulnerability in Jellyfin Media Server (CVSS 9.9). Includes proof-of-concept exploit, technical analysis, and detection tools.

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages