## https://sploitus.com/exploit?id=94F85AA7-B15A-5950-8EE5-C03E37FF8A2D
# CVE-2026-35031: Jellyfin Subtitle Upload Path Traversal to RCE
[](https://nvd.nist.gov/vuln/detail/CVE-2026-35031)
[](https://nvd.nist.gov/vuln/detail/CVE-2026-35031)
[](https://cwe.mitre.org/data/definitions/22.html)
[](https://jellyfin.org)
[](https://github.com/jellyfin/jellyfin/security/advisories/GHSA-9p5f-5x8v-x65m)
## 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 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 |
|---------|--------|-------|
| 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**
```bash
# 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**
```bash
# 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**
```bash
# 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**
```bash
# 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**
```bash
# 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**
```bash
# 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
```bash
# 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
- **NVD Entry:** https://nvd.nist.gov/vuln/detail/CVE-2026-35031
- **GitHub Advisory:** https://github.com/jellyfin/jellyfin/security/advisories/GHSA-9p5f-5x8v-x65m
- **Jellyfin Release v10.11.7:** https://github.com/jellyfin/jellyfin/releases/tag/v10.11.7
- **Jellyfin Documentation:** https://docs.jellyfin.org
### Related Vulnerabilities & Research
- CWE-22: Path Traversal - https://cwe.mitre.org/data/definitions/22.html
- LD_PRELOAD Exploitation: https://www.gnu.org/software/libc/manual/html_node/Dynamic-Linker.html
- Java Process Privilege Escalation Patterns
- Subtitle File Format Specifications (RFC standards)
### Security Tools & Resources
- Nmap: https://nmap.org
- Metasploit Framework: https://www.metasploit.com
- OWASP Path Traversal Guide: https://owasp.org/www-community/attacks/Path_Traversal
---
## Author
**Vulnerability Discovered & Documented By:**
**Kerem Oruc** (@keraattin)
- GitHub: https://github.com/keraattin
- Twitter/X: https://twitter.com/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