Skip to content

Commit 9afc917

Browse files
Merge commit from fork
Add test # Conflicts: # dgraph/cmd/alpha/run.go
1 parent 86d7606 commit 9afc917

4 files changed

Lines changed: 42 additions & 8 deletions

File tree

dgraph/cmd/alpha/http_test.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -838,6 +838,26 @@ func TestHealth(t *testing.T) {
838838
require.True(t, info[0].Uptime > int64(time.Duration(1)))
839839
}
840840

841+
// TestPprofCmdlineNotExposed ensures that /debug/pprof/cmdline is not reachable
842+
// without authentication. The endpoint exposes the full process command line,
843+
// which may include the admin token passed via --security "token=...".
844+
// The other pprof sub-endpoints should remain accessible.
845+
func TestPprofCmdlineNotExposed(t *testing.T) {
846+
// cmdline must be blocked — it leaks the admin token from process args.
847+
resp, err := http.Get(fmt.Sprintf("%s/debug/pprof/cmdline", addr))
848+
require.NoError(t, err)
849+
defer resp.Body.Close()
850+
require.Equal(t, http.StatusNotFound, resp.StatusCode,
851+
"/debug/pprof/cmdline should return 404; got %d", resp.StatusCode)
852+
853+
// Sanity-check that other pprof endpoints are still reachable.
854+
resp2, err := http.Get(fmt.Sprintf("%s/debug/pprof/heap", addr))
855+
require.NoError(t, err)
856+
defer resp2.Body.Close()
857+
require.Equal(t, http.StatusOK, resp2.StatusCode,
858+
"/debug/pprof/heap should return 200; got %d", resp2.StatusCode)
859+
}
860+
841861
func setDrainingMode(t *testing.T, enable bool, accessJwt string) {
842862
drainingRequest := `mutation drain($enable: Boolean) {
843863
draining(enable: $enable) {

dgraph/cmd/alpha/run.go

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -586,7 +586,20 @@ func setupServer(closer *z.Closer) {
586586
// Initialize the servers.
587587
x.ServerCloser.AddRunning(3)
588588
go serveGRPC(grpcListener, tlsCfg, x.ServerCloser)
589-
go x.StartListenHttpAndHttps(httpListener, tlsCfg, x.ServerCloser)
589+
590+
// Block /debug/pprof/cmdline — importing net/http/pprof registers it on
591+
// http.DefaultServeMux, but it exposes the full process command line which
592+
// may include the admin token from --security "token=...".
593+
serverHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
594+
if r.URL.Path == "/debug/pprof/cmdline" {
595+
http.NotFound(w, r)
596+
return
597+
}
598+
http.DefaultServeMux.ServeHTTP(w, r)
599+
})
600+
go x.StartListenHttpAndHttps(httpListener, tlsCfg, x.ServerCloser, serverHandler)
601+
602+
go x.StartListenHttpAndHttps(httpListener, tlsCfg, x.ServerCloser, serverHandler)
590603

591604
go func() {
592605
defer x.ServerCloser.Done()

dgraph/cmd/zero/run.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -310,7 +310,7 @@ func run() {
310310

311311
tlsCfg, err := x.LoadServerTLSConfig(Zero.Conf)
312312
x.Check(err)
313-
go x.StartListenHttpAndHttps(httpListener, tlsCfg, st.zero.closer)
313+
go x.StartListenHttpAndHttps(httpListener, tlsCfg, st.zero.closer, nil)
314314

315315
baseMux := http.NewServeMux()
316316
http.Handle("/", audit.AuditRequestHttp(baseMux))

x/server.go

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,17 +22,17 @@ var (
2222
ServerCloser = z.NewCloser(0)
2323
)
2424

25-
func StartListenHttpAndHttps(l net.Listener, tlsCfg *tls.Config, closer *z.Closer) {
25+
func StartListenHttpAndHttps(l net.Listener, tlsCfg *tls.Config, closer *z.Closer, h http.Handler) {
2626
defer closer.Done()
2727
m := cmux.New(l)
28-
startServers(m, tlsCfg)
28+
startServers(m, tlsCfg, h)
2929
err := m.Serve()
3030
if err != nil {
3131
glog.Errorf("error from cmux serve: %v", err)
3232
}
3333
}
3434

35-
func startServers(m cmux.CMux, tlsConf *tls.Config) {
35+
func startServers(m cmux.CMux, tlsConf *tls.Config, h http.Handler) {
3636
httpRule := m.Match(func(r io.Reader) bool {
3737
// no tls config is provided. http is being used.
3838
if tlsConf == nil {
@@ -48,19 +48,20 @@ func startServers(m cmux.CMux, tlsConf *tls.Config) {
4848
// monitoring tools which operate without authentication.
4949
return strings.HasPrefix(path, "/health")
5050
})
51-
go startListen(httpRule)
51+
go startListen(httpRule, h)
5252

5353
// if tls is enabled, make tls encryption based connections as default
5454
if tlsConf != nil {
5555
httpsRule := m.Match(cmux.Any())
5656
// this is chained listener. tls listener will decrypt
5757
// the message and send it in plain text to HTTP server
58-
go startListen(tls.NewListener(httpsRule, tlsConf))
58+
go startListen(tls.NewListener(httpsRule, tlsConf), h)
5959
}
6060
}
6161

62-
func startListen(l net.Listener) {
62+
func startListen(l net.Listener, h http.Handler) {
6363
srv := &http.Server{
64+
Handler: h, // nil falls back to http.DefaultServeMux
6465
ReadTimeout: 10 * time.Second,
6566
WriteTimeout: 600 * time.Second,
6667
IdleTimeout: 2 * time.Minute,

0 commit comments

Comments
 (0)