From 4d8df2b2c05ba4d7b51e373e7b7e98cccf031a15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20=22Pisco=22=20Fernandes?= Date: Thu, 7 May 2026 18:00:53 +0100 Subject: [PATCH] TUN-10513: Disable /debug/pprof/cmdline endpoint --- metrics/metrics.go | 7 ++++- metrics/pprof_cmdline_test.go | 48 +++++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+), 1 deletion(-) create mode 100644 metrics/pprof_cmdline_test.go diff --git a/metrics/metrics.go b/metrics/metrics.go index 2a4fe993..de6cad56 100644 --- a/metrics/metrics.go +++ b/metrics/metrics.go @@ -5,7 +5,7 @@ import ( "fmt" "net" "net/http" - _ "net/http/pprof" + _ "net/http/pprof" //nolint:gosec // G108: the sensitive /debug/pprof/cmdline endpoint is explicitly blocked in newMetricsHandler "runtime" "sync" "time" @@ -70,6 +70,11 @@ func newMetricsHandler( log *zerolog.Logger, ) *http.ServeMux { router := http.NewServeMux() + // Block /debug/pprof/cmdline to prevent leaking secret command-line arguments + // (e.g. tunnel tokens) that are exposed via os.Args. + router.HandleFunc("/debug/pprof/cmdline", func(w http.ResponseWriter, r *http.Request) { + http.Error(w, "forbidden", http.StatusForbidden) + }) router.Handle("/debug/", http.DefaultServeMux) router.Handle("/metrics", promhttp.Handler()) router.HandleFunc("/healthcheck", func(w http.ResponseWriter, r *http.Request) { diff --git a/metrics/pprof_cmdline_test.go b/metrics/pprof_cmdline_test.go new file mode 100644 index 00000000..69840303 --- /dev/null +++ b/metrics/pprof_cmdline_test.go @@ -0,0 +1,48 @@ +package metrics + +import ( + "net/http" + "net/http/httptest" + "testing" + + "github.com/google/uuid" + "github.com/rs/zerolog" + "github.com/stretchr/testify/assert" + + "github.com/cloudflare/cloudflared/diagnostic" +) + +func testHandler(t *testing.T) *http.ServeMux { + t.Helper() + + log := zerolog.Nop() + return newMetricsHandler(Config{ + DiagnosticHandler: diagnostic.NewDiagnosticHandler( + &log, 0, nil, uuid.Nil, uuid.Nil, nil, map[string]string{}, nil, + ), + }, &log) +} + +func TestPprofCmdlineEndpointIsBlocked(t *testing.T) { + t.Parallel() + + handler := testHandler(t) + req := httptest.NewRequest(http.MethodGet, "/debug/pprof/cmdline", nil) + w := httptest.NewRecorder() + handler.ServeHTTP(w, req) + + assert.Equal(t, http.StatusForbidden, w.Code) +} + +func TestOtherPprofEndpointsStillWork(t *testing.T) { + t.Parallel() + + handler := testHandler(t) + + // /debug/pprof/ index should still be served by DefaultServeMux + req := httptest.NewRequest(http.MethodGet, "/debug/pprof/", nil) + w := httptest.NewRecorder() + handler.ServeHTTP(w, req) + + assert.Equal(t, http.StatusOK, w.Code) +}