Files
pad/internal
xarmian 7d3b468fc8 feat(server): gate /metrics behind loopback + bearer token (TASK-653) (#180)
cmd/pad/main.go:277 unconditionally registered Prometheus metrics and
internal/server/server.go:229 served /metrics with no auth/CSRF. Any
caller on the network could read workspace counts, API usage patterns,
and (via label enumeration) user/workspace IDs.

Three-layer gate:

1. Loopback-only default. No PAD_METRICS_TOKEN configured → /metrics
   accepts loopback peers only (safe for self-hosters running Prometheus
   on the same host, which is the common case). Non-loopback peers get
   403 with a clear message.

2. Bearer-token mode. PAD_METRICS_TOKEN set → every scrape must send
   "Authorization: Bearer <token>", compared in constant time. Missing
   or wrong header → 401 with WWW-Authenticate: Bearer realm="metrics".

3. Rate-limit/logging chain still wraps the endpoint from the outer
   router.Use calls.

Wiring:
- internal/config/config.go — MetricsToken field + PAD_METRICS_TOKEN env.
- cmd/pad/main.go — plumb cfg.MetricsToken into SetMetricsToken.
- .env.example — document PAD_METRICS_TOKEN with openssl-rand hint.
- internal/server/server.go — metricsAuth middleware + subtle.ConstantTimeCompare.

Tests: metrics_auth_test.go covers loopback allowed, LAN denied,
missing/wrong/correct Bearer, non-Bearer scheme rejected, WWW-Authenticate
header, and the SetMetrics-absent 404.

Parent: PLAN-643 (OSS Security Hardening).
2026-04-21 21:27:33 -04:00
..
2026-03-26 01:52:36 +00:00
2026-03-26 01:52:36 +00:00