Netdata Security Testing: Unauthenticated Metrics API, Stream Registry, SSRF, and Agent Exposure

Netdata is one of the most widely deployed real-time infrastructure monitoring tools, installed on millions of Linux servers via one-line install scripts, Docker, Kubernetes, and package managers. Its default configuration presents significant information disclosure: Netdata listens on port 19999 and serves both the web dashboard and the full metrics REST API without authentication by default — any attacker who can reach this port gains complete visibility into the host's CPU usage, memory consumption, disk I/O, network traffic per interface and connection, running process names and PIDs, open files, active users, and system calls; the /api/v1/info endpoint returns the host's operating system type and version, Netdata version, hostname, and cloud detection information without authentication; Netdata's stream receiver allows child agents to stream metrics to a parent Netdata instance — the stream authorization key in stream.conf must be protected, as a wildcard allow from = * with a known key permits unauthorized metric injection; Netdata Cloud registration transmits agent identifiers and host metadata to Netdata's cloud infrastructure — deployments with strict data residency requirements must review cloud telemetry settings; and Netdata alarms and notification systems support webhook callbacks — misconfigured webhook URLs can receive monitoring alert data including alert conditions and host performance states. This guide covers systematic Netdata security assessment.

Table of Contents

  1. Netdata Discovery on Port 19999
  2. Metrics API Information Disclosure
  3. Stream API Key Testing
  4. Process and Network Topology Exposure
  5. Netdata Security Hardening

Netdata Discovery on Port 19999

# Netdata default port 19999 — unauthenticated by default
# Check if Netdata is publicly accessible
curl -s -o /dev/null -w "%{http_code}" \
  "http://target.example.com:19999/" 2>/dev/null

# Get Netdata version and host info without authentication
curl -s "http://target.example.com:19999/api/v1/info" 2>/dev/null | \
  python3 -c "
import json,sys
d = json.load(sys.stdin)
print(f'Hostname: {d.get(\"hostname\",\"?\")}')
print(f'OS: {d.get(\"os\",\"?\")} version={d.get(\"os_version\",\"?\")}')
print(f'Netdata version: {d.get(\"version\",\"?\")}')
print(f'Cloud: {d.get(\"cloud\",\"?\")}')
print(f'Memory (MB): {d.get(\"total_disk_space_gb\",\"?\")} disk / {d.get(\"ram_total\",\"?\")} RAM')
" 2>/dev/null

Metrics API Information Disclosure

# Netdata metrics API — all data accessible without authentication
NETDATA="http://target.example.com:19999"

# Get all chart names (reveals running services and monitoring scope)
curl -s "${NETDATA}/api/v1/charts" 2>/dev/null | \
  python3 -c "
import json,sys
d = json.load(sys.stdin)
charts = d.get('charts',{})
print(f'Total charts: {len(charts)}')
# Show chart families (reveals installed software)
families = set(v.get('family','?') for v in charts.values())
print(f'Service families detected: {sorted(families)[:20]}')
" 2>/dev/null

# Get active network connections (TCP/UDP) — exposes internal services
curl -s "${NETDATA}/api/v1/data?chart=net_sockets&after=-30&format=json" \
  2>/dev/null | python3 -c "
import json,sys
d=json.load(sys.stdin)
print(f'Network socket data points: {d.get(\"points\",0)}')
" 2>/dev/null

# Get running processes via processes chart
curl -s "${NETDATA}/api/v1/allmetrics?format=json&types=charts&chart=groups.cpu_util_percent" \
  2>/dev/null | python3 -c "
import json,sys
d = json.load(sys.stdin)
# Process group data reveals process names and resource consumption
if isinstance(d, dict):
    for k in list(d.keys())[:10]:
        print(f'  Process group: {k}')
" 2>/dev/null

Netdata Security Hardening

Netdata Security Hardening Checklist:
Security TestMethodRisk
Port 19999 unauthenticated metrics dashboardcurl http://target:19999/ — full dashboard and metrics API accessible without any credentialsHigh
/api/v1/info hostname and OS version disclosurecurl http://target:19999/api/v1/info — reveals hostname, OS version, RAM, CPU count, Netdata version without authMedium
Running process names and resource usage exposedcurl http://target:19999/api/v1/charts — process group charts reveal all running software names and resource consumptionHigh
Active network connections and listening portsNetdata net_* charts expose network interface traffic, connections, and listening port statistics without authenticationHigh
Stream API accepting unauthorized child agentsstream.conf with wildcard allow from = * accepts metric injection from attacker-controlled Netdata agentsMedium
Alarm webhook delivering monitoring data to external endpointsConfigured webhook URL receives all Netdata alert conditions including service names and performance thresholdsMedium

Automate Netdata Security Testing

Ironimo tests Netdata deployments for port 19999 unauthenticated access exposing the full metrics API and dashboard, /api/v1/info hostname and OS version disclosure without authentication, running process names and resource usage exposure through Netdata charts, active network connection and listening port statistics accessible without credentials, stream API configuration accepting unauthorized child agent connections, and alarm notification webhooks configured to deliver monitoring event data to external endpoints.

Start free scan