Tautulli Security Testing: API Key, Notification Webhook SSRF, Plex Token, and Activity History

Tautulli is one of the most widely deployed self-hosted Plex analytics and notification applications, collecting detailed viewing statistics for all Plex users and sending notifications when streams start or stop. Its security profile is significant for two reasons: the Plex authentication token it stores gives full Plex Media Server API access, and it accumulates detailed behavioral data on all users. Its security assessment covers: Tautulli's REST API accepts an API key configured in Settings > Web Interface — this key provides read access to all viewing history, user statistics, and notification configurations; Tautulli stores the Plex owner's X-Plex-Token in its config.ini configuration file — this token provides full Plex API access including library management and user administration; Tautulli's notification agent webhooks make outbound HTTP POST requests to configured URLs on Plex events — webhook URLs targeting internal services create an SSRF vector; and Tautulli's get_history API endpoint returns the complete viewing history for all users including IP addresses, device information, and watch duration. This guide covers systematic Tautulli security assessment.

Table of Contents

  1. API Key Extraction and Enumeration
  2. Plex Token Exposure
  3. Notification Webhook SSRF
  4. Tautulli Security Hardening

API Key Extraction and Enumeration

# Tautulli API — single API key controls all read/write operations
TAUTULLI_URL="https://tautulli.example.com"
API_KEY="your-tautulli-api-key"

# Get all users on the Plex server
curl -s "${TAUTULLI_URL}/api/v2?apikey=${API_KEY}&cmd=get_users" \
  2>/dev/null | python3 -c "
import json,sys
d=json.load(sys.stdin)
users = d.get('response',{}).get('data',{}).get('data',[])
print(f'Plex users: {len(users)}')
for u in users:
    print(f'  {u.get(\"username\")} ({u.get(\"email\",\"?\")}) shared_libraries={len(u.get(\"shared_libraries\",[]))}')
" 2>/dev/null

# Get full viewing history for all users
curl -s "${TAUTULLI_URL}/api/v2?apikey=${API_KEY}&cmd=get_history&length=100" \
  2>/dev/null | python3 -c "
import json,sys
d=json.load(sys.stdin)
history = d.get('response',{}).get('data',{}).get('data',[])
print(f'History entries: {len(history)}')
for h in history[:10]:
    print(f'  {h.get(\"user\")} watched {h.get(\"full_title\")} from {h.get(\"ip_address\")} on {h.get(\"player\")}')
" 2>/dev/null

# Get server statistics and library info
curl -s "${TAUTULLI_URL}/api/v2?apikey=${API_KEY}&cmd=get_libraries" \
  2>/dev/null | python3 -c "
import json,sys
d=json.load(sys.stdin)
libs = d.get('response',{}).get('data',[])
print(f'Libraries: {len(libs)}')
for l in libs:
    print(f'  {l.get(\"section_name\")} type={l.get(\"section_type\")} count={l.get(\"count\")}')
" 2>/dev/null

Plex Token Exposure

# Tautulli config.ini — stores Plex authentication token in plaintext
# The plex_token grants full Plex Media Server API access

# If you have filesystem access to the Tautulli config directory
grep "plex_token" /path/to/tautulli/config/config.ini 2>/dev/null

# Alternatively, extract via Tautulli API
API_KEY="your-tautulli-api-key"
TAUTULLI_URL="https://tautulli.example.com"

curl -s "${TAUTULLI_URL}/api/v2?apikey=${API_KEY}&cmd=get_server_info" \
  2>/dev/null | python3 -c "
import json,sys
d=json.load(sys.stdin)
server = d.get('response',{}).get('data',{})
print(f'Plex server: {server.get(\"pms_name\")}')
print(f'Version: {server.get(\"pms_version\")}')
print(f'Plex token (if exposed): {server.get(\"pms_token\",\"not in response\")}')
" 2>/dev/null

# With a Plex token, access the Plex Media Server API directly
PLEX_TOKEN="extracted-plex-token"
PLEX_URL="http://localhost:32400"
curl -s "${PLEX_URL}/library/sections?X-Plex-Token=${PLEX_TOKEN}" 2>/dev/null | head -20

Tautulli Security Hardening

Tautulli Security Hardening Checklist:
Security TestMethodRisk
API key access to complete Plex viewing historyGET /api/v2?apikey=KEY&cmd=get_history — returns complete viewing history for all Plex users including username, IP address, device, content watched, and watch durationHigh
Plex token in config.ini giving full Plex API accessRead /config/config.ini plex_token field — token provides full Plex Media Server API access including library management, user administration, and stream controlCritical
Notification webhook SSRF on Plex stream eventsConfigure webhook URL to internal address — Tautulli server makes outbound POST to webhook URL on every Plex stream start/stop event; any Plex user starting a stream can trigger the SSRFHigh
All Plex user enumeration via APIGET /api/v2?apikey=KEY&cmd=get_users — lists all Plex users with usernames, emails, and shared library access for the entire Plex serverHigh
Unauthenticated web interface accessGET / without credentials — full Tautulli web UI accessible without login when HTTP_AUTH not configured; all dashboards and history data viewableHigh
Notification agent credential extractionGET /api/v2?apikey=KEY&cmd=get_notifiers — lists all notification agents; some return stored credentials (SMTP password, webhook URLs with embedded tokens) in the responseMedium

Automate Tautulli Security Testing

Ironimo tests Tautulli deployments for API key access exposing complete Plex viewing history for all users including IP addresses and device information, Plex authentication token extraction from config.ini giving full Plex Media Server API access, notification webhook SSRF triggered by Plex stream events pointing to internal services, all Plex user enumeration via the API, unauthenticated web interface access, and notification agent credential extraction.

Start free scan