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.
# 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
# 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
# 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
| Security Test | Method | Risk |
|---|---|---|
| Calibre Content Server credential extraction | GET /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 interface | High |
| Indexer credential extraction | GET /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 credentials | High |
| Download client credential exposure | GET /api/v1/downloadclient — returns host, port, username, and password for every configured download client; same exposure as other *arr applications | High |
| Import list API key exposure | GET /api/v1/importlist — returns credentials for GoodReads, BookShelf, LazyLibrarian, and other configured import sources including API keys and login credentials | Medium |
| Custom Script notification code execution | GET /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 privileges | Critical (requires API access) |
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