Jellyseerr is a fork of Overseerr designed to support both Plex and Jellyfin, widely deployed as the primary media request interface for home lab users and small media server communities. Its security profile extends beyond Jellyseerr itself because it serves as an authentication bridge: Jellyseerr stores the Plex authentication token and Jellyfin admin password in its configuration to communicate with media servers, and these credentials are accessible to anyone with Jellyseerr admin access; Jellyseerr's REST API key in Settings > General provides full read/write access to all media requests, user accounts, and service configurations including Radarr and Sonarr connection details; Jellyseerr allows any authenticated Plex or Jellyfin user to self-register and submit media requests — the scope of who can access the request interface depends on whether the server owner has restricted registration; notification webhooks for request events (approval, availability) make outbound HTTP POST requests creating SSRF; and the /api/v1/user endpoint enumerates all registered users including email addresses. This guide covers systematic Jellyseerr security assessment.
# Jellyseerr API — key-based access to all settings and request data
JELLYSEERR_URL="https://jellyseerr.example.com"
API_KEY="your-jellyseerr-api-key"
# Get main settings — includes API key and configuration
curl -s "${JELLYSEERR_URL}/api/v1/settings/main" \
-H "X-Api-Key: ${API_KEY}" 2>/dev/null | python3 -c "
import json,sys
d=json.load(sys.stdin)
print(f'App title: {d.get(\"applicationTitle\")}')
print(f'App URL: {d.get(\"applicationUrl\")}')
print(f'New user login: {d.get(\"newPlexLogin\")}')
print(f'Hide available: {d.get(\"hideAvailable\")}')
" 2>/dev/null
# Get Plex settings — may contain Plex token
curl -s "${JELLYSEERR_URL}/api/v1/settings/plex" \
-H "X-Api-Key: ${API_KEY}" 2>/dev/null | python3 -c "
import json,sys
d=json.load(sys.stdin)
print(f'Plex hostname: {d.get(\"hostname\")}')
print(f'Plex port: {d.get(\"port\")}')
print(f'Plex token: {d.get(\"authToken\",\"not in response\")}')
" 2>/dev/null
# Get Jellyfin settings — contains admin credentials
curl -s "${JELLYSEERR_URL}/api/v1/settings/jellyfin" \
-H "X-Api-Key: ${API_KEY}" 2>/dev/null | python3 -c "
import json,sys
d=json.load(sys.stdin)
print(f'Jellyfin hostname: {d.get(\"hostname\")}')
print(f'Jellyfin port: {d.get(\"port\")}')
print(f'Jellyfin API key: {d.get(\"apiKey\",\"not in response\")}')
print(f'Jellyfin user: {d.get(\"jellyfinExternalHost\",\"?\")}')
" 2>/dev/null
# Get all Radarr and Sonarr configurations
curl -s "${JELLYSEERR_URL}/api/v1/settings/radarr" \
-H "X-Api-Key: ${API_KEY}" 2>/dev/null | python3 -c "
import json,sys
servers = json.load(sys.stdin)
for s in servers:
print(f' Radarr [{s.get(\"id\")}] {s.get(\"name\")} url={s.get(\"hostname\")}:{s.get(\"port\")} apiKey={s.get(\"apiKey\")}')
" 2>/dev/null
# Jellyseerr user enumeration — all registered users accessible via API
JELLYSEERR_URL="https://jellyseerr.example.com"
API_KEY="your-jellyseerr-api-key"
# List all registered users with their details
curl -s "${JELLYSEERR_URL}/api/v1/user?take=100&skip=0" \
-H "X-Api-Key: ${API_KEY}" 2>/dev/null | python3 -c "
import json,sys
d=json.load(sys.stdin)
users = d.get('results',[])
total = d.get('pageInfo',{}).get('results',len(users))
print(f'Users: {total}')
for u in users:
print(f' [{u.get(\"id\")}] {u.get(\"displayName\")} email={u.get(\"email\",\"N/A\")} role={u.get(\"permissions\")} requests={u.get(\"requestCount\")}')
" 2>/dev/null
# Get individual user details — includes watch history and request list
USER_ID=1
curl -s "${JELLYSEERR_URL}/api/v1/user/${USER_ID}" \
-H "X-Api-Key: ${API_KEY}" 2>/dev/null | python3 -c "
import json,sys
u=json.load(sys.stdin)
print(f'User: {u.get(\"displayName\")} ({u.get(\"email\")})')
print(f'Permissions: {u.get(\"permissions\")}')
print(f'Requests: {u.get(\"requestCount\")}')
print(f'Plex username: {u.get(\"plexUsername\")}')
" 2>/dev/null
| Security Test | Method | Risk |
|---|---|---|
| API key access to all service credentials | GET /api/v1/settings/plex — Plex auth token; GET /api/v1/settings/jellyfin — Jellyfin API key; GET /api/v1/settings/radarr — Radarr API keys; GET /api/v1/settings/sonarr — Sonarr API keys | Critical |
| User enumeration with email addresses | GET /api/v1/user with X-Api-Key header — returns displayName, email, plexUsername, permissions, and request count for every registered user | High |
| Notification webhook SSRF on request events | Configure webhook notification URL to internal address — Jellyseerr server makes outbound POST on request creation/approval/availability events; any registered user submitting a request can trigger the SSRF | High |
| Open user registration from any Plex account | Authenticate with any Plex account and access Jellyseerr — by default, any Plex account holder can self-register and begin submitting media requests; combined with auto-approval settings this may create unauthorized media downloads | Medium |
| settings.json credential exposure | Read /config/settings.json — contains all stored service credentials in plaintext; accessible via path traversal in another service or direct filesystem access to the data directory | High |
Ironimo tests Jellyseerr deployments for API key access exposing Plex authentication tokens and Jellyfin API keys, Radarr and Sonarr API key extraction from service settings, user enumeration with email addresses via the user API endpoint, notification webhook SSRF triggered by any request creation event, open user registration from any Plex account holder, and settings.json credential exposure.
Start free scan