Lidarr Security Testing: API Key, Indexer Credentials, Download Client, and Music Automation

Lidarr is the music automation application in the *arr stack, managing music library downloads with the same architecture as Sonarr and Radarr. Its security profile is nearly identical to its sibling applications: Lidarr's API key provides full access to all indexer credentials, download client credentials, and notification agent secrets; GET /api/v1/indexer returns all configured indexer credentials including private tracker API keys and passkeys; GET /api/v1/downloadclient returns connection details and credentials for every configured download client (qBittorrent, SABnzbd, NZBGet); Lidarr's Import Lists can be configured with Last.fm API tokens and other music metadata service credentials stored in the configuration; and Lidarr's Custom Script notification agent executes arbitrary commands on the host when triggered. This guide covers systematic Lidarr security assessment as part of a complete *arr stack audit.

Table of Contents

  1. API Key and System Configuration
  2. Indexer Credential Extraction
  3. Download Client Credential Extraction
  4. Lidarr Security Hardening

API Key and System Configuration

# Lidarr API — identical architecture to Sonarr and Radarr
LIDARR_URL="https://lidarr.example.com"
API_KEY="your-lidarr-api-key"

# Get system status — confirms API key works and reveals version
curl -s "${LIDARR_URL}/api/v1/system/status?apikey=${API_KEY}" 2>/dev/null | python3 -c "
import json,sys
d=json.load(sys.stdin)
print(f'Version: {d.get(\"version\")}')
print(f'Branch: {d.get(\"branch\")}')
print(f'OS: {d.get(\"osName\")}')
print(f'DB: {d.get(\"dbType\")}')
print(f'Runtime version: {d.get(\"runtimeVersion\")}')
" 2>/dev/null

# Get host configuration — reveals authentication settings and base URL
curl -s "${LIDARR_URL}/api/v1/config/host?apikey=${API_KEY}" 2>/dev/null | python3 -c "
import json,sys
d=json.load(sys.stdin)
print(f'Auth method: {d.get(\"authenticationMethod\")}')
print(f'Auth required: {d.get(\"authenticationRequired\")}')
print(f'Bind address: {d.get(\"bindAddress\")}')
print(f'Port: {d.get(\"port\")}')
print(f'URL base: {d.get(\"urlBase\")}')
" 2>/dev/null

# Enumerate artists in library — confirms what music is managed
curl -s "${LIDARR_URL}/api/v1/artist?apikey=${API_KEY}" 2>/dev/null | python3 -c "
import json,sys
d=json.load(sys.stdin)
print(f'Artists in library: {len(d)}')
for a in d[:10]:
    print(f'  {a.get(\"artistName\")} — {a.get(\"albumCount\",0)} albums, status={a.get(\"status\")}')
" 2>/dev/null

Indexer Credential Extraction

# Lidarr indexers — same credential extraction as Sonarr and Radarr
LIDARR_URL="https://lidarr.example.com"
API_KEY="your-lidarr-api-key"

# Extract all indexer credentials
curl -s "${LIDARR_URL}/api/v1/indexer?apikey=${API_KEY}" 2>/dev/null | python3 -c "
import json,sys
indexers = json.load(sys.stdin)
print(f'Indexers configured: {len(indexers)}')
for idx in indexers:
    print(f'  [{idx.get(\"id\")}] {idx.get(\"name\")} [{idx.get(\"implementation\")}]')
    for field in idx.get('fields',[]):
        fname = field.get('name','')
        fval = field.get('value','')
        if fval and isinstance(fval, str):
            sensitive = ['apikey','passkey','apiKey','password','username','cookie']
            if any(s.lower() in fname.lower() for s in sensitive):
                print(f'    CREDENTIAL {fname}: {fval}')
            elif fname.lower() in ['baseurl','url']:
                print(f'    URL: {fval}')
" 2>/dev/null

Download Client Credential Extraction

# Lidarr download clients — qBittorrent, SABnzbd, NZBGet credentials
LIDARR_URL="https://lidarr.example.com"
API_KEY="your-lidarr-api-key"

# Extract all download client credentials
curl -s "${LIDARR_URL}/api/v1/downloadclient?apikey=${API_KEY}" 2>/dev/null | python3 -c "
import json,sys
clients = json.load(sys.stdin)
print(f'Download clients: {len(clients)}')
for c in clients:
    print(f'  [{c.get(\"id\")}] {c.get(\"name\")} [{c.get(\"implementation\")}] enable={c.get(\"enable\")}')
    for field in c.get('fields',[]):
        fname = field.get('name','')
        fval = field.get('value','')
        if fval and fname.lower() in ['host','port','username','password','apikey','urlbase']:
            print(f'    {fname}: {fval}')
" 2>/dev/null

# Get all notification agents — Custom Script gives code execution path
curl -s "${LIDARR_URL}/api/v1/notification?apikey=${API_KEY}" 2>/dev/null | python3 -c "
import json,sys
notifs = json.load(sys.stdin)
print(f'Notification agents: {len(notifs)}')
for n in notifs:
    print(f'  [{n.get(\"id\")}] {n.get(\"name\")} [{n.get(\"implementation\")}]')
    for field in n.get('fields',[]):
        fname = field.get('name','')
        fval = field.get('value','')
        if fval and isinstance(fval, str):
            if fname.lower() in ['path','arguments'] or 'token' in fname.lower() or 'key' in fname.lower():
                print(f'    {fname}: {fval}')
" 2>/dev/null

Lidarr Security Hardening

Lidarr Security Hardening Checklist:
Security TestMethodRisk
Indexer credential extractionGET /api/v1/indexer — returns all configured indexer credentials including private tracker API keys, passkeys, and authentication details; identical architecture to Sonarr and Radarr indexer exposureHigh
Download client credential exposureGET /api/v1/downloadclient — returns host, port, username, password, and API key for every configured download client (qBittorrent, SABnzbd, NZBGet, Deluge, Transmission)High
Custom Script notification code executionGET /api/v1/notification to find Custom Script agents, then POST /api/v1/notification/test — triggers the configured script path on the Lidarr host; code execution with Lidarr service account privilegesCritical (requires API access)
Import List API key exposureGET /api/v1/importlist — returns all configured import lists including Last.fm API token, ListenBrainz token, and credentials for any external music metadata service configured for automatic artist importsMedium
Music library enumerationGET /api/v1/artist and /api/v1/album — enumerates all artists and albums in the managed music library; reveals content interests and music collection scopeLow

Automate Lidarr Security Testing

Ironimo tests Lidarr deployments for the complete credential chain including indexer API key and passkey extraction, download client credential harvesting (qBittorrent, SABnzbd, NZBGet), Custom Script notification agent code execution risk, import list API key exposure, authentication bypass when no credentials are configured, music library enumeration, and config.xml API key access.

Start free scan