VYPR
Moderate severityNVD Advisory· Published Mar 31, 2022· Updated Apr 23, 2025

Exposure of Sensitive Information in Pomerium

CVE-2022-24797

Description

Pomerium is an identity-aware access proxy. In distributed service mode, Pomerium's Authenticate service exposes pprof debug and prometheus metrics handlers to untrusted traffic. This can leak potentially sensitive environmental information or lead to limited denial of service conditions. This issue is patched in version v0.17.1 Workarounds: Block access to /debug and /metrics paths on the authenticate service. This can be done with any L7 proxy, including Pomerium's own proxy service.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
github.com/pomerium/pomeriumGo
>= 0.16.0, < 0.17.10.17.1

Affected products

1

Patches

1
b435f73e2b54

authenticate: fix debug and metrics endpoints (#3212)

https://github.com/pomerium/pomeriumCaleb DoxseyMar 30, 2022via ghsa
16 files changed · +167 128
  • config/config.go+6 0 modified
    @@ -18,6 +18,10 @@ type Config struct {
     	HTTPPort string
     	// OutboundPort is the port the outbound gRPC listener is running on.
     	OutboundPort string
    +	// MetricsPort is the port the metrics listener is running on.
    +	MetricsPort string
    +	// DebugPort is the port the debug listener is running on.
    +	DebugPort string
     }
     
     // Clone creates a clone of the config.
    @@ -32,6 +36,8 @@ func (cfg *Config) Clone() *Config {
     		GRPCPort:     cfg.GRPCPort,
     		HTTPPort:     cfg.HTTPPort,
     		OutboundPort: cfg.OutboundPort,
    +		MetricsPort:  cfg.MetricsPort,
    +		DebugPort:    cfg.DebugPort,
     	}
     }
     
    
  • config/config_source.go+5 1 modified
    @@ -110,13 +110,15 @@ func NewFileOrEnvironmentSource(
     		return nil, err
     	}
     
    -	ports, err := netutil.AllocatePorts(3)
    +	ports, err := netutil.AllocatePorts(5)
     	if err != nil {
     		return nil, err
     	}
     	grpcPort := ports[0]
     	httpPort := ports[1]
     	outboundPort := ports[2]
    +	metricsPort := ports[3]
    +	debugPort := ports[4]
     
     	cfg := &Config{
     		Options:      options,
    @@ -125,6 +127,8 @@ func NewFileOrEnvironmentSource(
     		GRPCPort:     grpcPort,
     		HTTPPort:     httpPort,
     		OutboundPort: outboundPort,
    +		MetricsPort:  metricsPort,
    +		DebugPort:    debugPort,
     	}
     	metrics.SetConfigInfo(ctx, cfg.Options.Services, "local", cfg.Checksum(), true)
     
    
  • config/envoyconfig/bootstrap_test.go+5 5 modified
    @@ -11,7 +11,7 @@ import (
     )
     
     func TestBuilder_BuildBootstrapAdmin(t *testing.T) {
    -	b := New("local-grpc", "local-http", filemgr.NewManager(), nil)
    +	b := New("local-grpc", "local-http", "local-metrics", filemgr.NewManager(), nil)
     	t.Run("valid", func(t *testing.T) {
     		adminCfg, err := b.BuildBootstrapAdmin(&config.Config{
     			Options: &config.Options{
    @@ -41,7 +41,7 @@ func TestBuilder_BuildBootstrapAdmin(t *testing.T) {
     }
     
     func TestBuilder_BuildBootstrapLayeredRuntime(t *testing.T) {
    -	b := New("localhost:1111", "localhost:2222", filemgr.NewManager(), nil)
    +	b := New("localhost:1111", "localhost:2222", "localhost:3333", filemgr.NewManager(), nil)
     	staticCfg, err := b.BuildBootstrapLayeredRuntime()
     	assert.NoError(t, err)
     	testutil.AssertProtoJSONEqual(t, `
    @@ -58,7 +58,7 @@ func TestBuilder_BuildBootstrapLayeredRuntime(t *testing.T) {
     
     func TestBuilder_BuildBootstrapStaticResources(t *testing.T) {
     	t.Run("valid", func(t *testing.T) {
    -		b := New("localhost:1111", "localhost:2222", filemgr.NewManager(), nil)
    +		b := New("localhost:1111", "localhost:2222", "localhost:3333", filemgr.NewManager(), nil)
     		staticCfg, err := b.BuildBootstrapStaticResources()
     		assert.NoError(t, err)
     		testutil.AssertProtoJSONEqual(t, `
    @@ -90,14 +90,14 @@ func TestBuilder_BuildBootstrapStaticResources(t *testing.T) {
     		`, staticCfg)
     	})
     	t.Run("bad gRPC address", func(t *testing.T) {
    -		b := New("xyz:zyx", "localhost:2222", filemgr.NewManager(), nil)
    +		b := New("xyz:zyx", "localhost:2222", "localhost:3333", filemgr.NewManager(), nil)
     		_, err := b.BuildBootstrapStaticResources()
     		assert.Error(t, err)
     	})
     }
     
     func TestBuilder_BuildBootstrapStatsConfig(t *testing.T) {
    -	b := New("local-grpc", "local-http", filemgr.NewManager(), nil)
    +	b := New("local-grpc", "local-http", "local-metrics", filemgr.NewManager(), nil)
     	t.Run("valid", func(t *testing.T) {
     		statsCfg, err := b.BuildBootstrapStatsConfig(&config.Config{
     			Options: &config.Options{
    
  • config/envoyconfig/builder.go+11 8 modified
    @@ -7,23 +7,26 @@ import (
     
     // A Builder builds envoy config from pomerium config.
     type Builder struct {
    -	localGRPCAddress string
    -	localHTTPAddress string
    -	filemgr          *filemgr.Manager
    -	reproxy          *reproxy.Handler
    +	localGRPCAddress    string
    +	localHTTPAddress    string
    +	localMetricsAddress string
    +	filemgr             *filemgr.Manager
    +	reproxy             *reproxy.Handler
     }
     
     // New creates a new Builder.
     func New(
     	localGRPCAddress string,
     	localHTTPAddress string,
    +	localMetricsAddress string,
     	fileManager *filemgr.Manager,
     	reproxyHandler *reproxy.Handler,
     ) *Builder {
     	return &Builder{
    -		localGRPCAddress: localGRPCAddress,
    -		localHTTPAddress: localHTTPAddress,
    -		filemgr:          fileManager,
    -		reproxy:          reproxyHandler,
    +		localGRPCAddress:    localGRPCAddress,
    +		localHTTPAddress:    localHTTPAddress,
    +		localMetricsAddress: localMetricsAddress,
    +		filemgr:             fileManager,
    +		reproxy:             reproxyHandler,
     	}
     }
    
  • config/envoyconfig/clusters.go+10 0 modified
    @@ -34,6 +34,10 @@ func (b *Builder) BuildClusters(ctx context.Context, cfg *config.Config) ([]*env
     		Scheme: "http",
     		Host:   b.localHTTPAddress,
     	}
    +	metricsURL := &url.URL{
    +		Scheme: "http",
    +		Host:   b.localMetricsAddress,
    +	}
     	authorizeURLs, err := cfg.Options.GetInternalAuthorizeURLs()
     	if err != nil {
     		return nil, err
    @@ -53,6 +57,11 @@ func (b *Builder) BuildClusters(ctx context.Context, cfg *config.Config) ([]*env
     		return nil, err
     	}
     
    +	controlMetrics, err := b.buildInternalCluster(ctx, cfg.Options, "pomerium-control-plane-metrics", []*url.URL{metricsURL}, upstreamProtocolAuto)
    +	if err != nil {
    +		return nil, err
    +	}
    +
     	authorizeCluster, err := b.buildInternalCluster(ctx, cfg.Options, "pomerium-authorize", authorizeURLs, upstreamProtocolHTTP2)
     	if err != nil {
     		return nil, err
    @@ -74,6 +83,7 @@ func (b *Builder) BuildClusters(ctx context.Context, cfg *config.Config) ([]*env
     	clusters := []*envoy_config_cluster_v3.Cluster{
     		controlGRPC,
     		controlHTTP,
    +		controlMetrics,
     		authorizeCluster,
     		databrokerCluster,
     	}
    
  • config/envoyconfig/clusters_test.go+3 3 modified
    @@ -25,7 +25,7 @@ func Test_buildPolicyTransportSocket(t *testing.T) {
     	cacheDir, _ := os.UserCacheDir()
     	customCA := filepath.Join(cacheDir, "pomerium", "envoy", "files", "custom-ca-32484c314b584447463735303142374c31414145374650305a525539554938594d524855353757313942494d473847535231.pem")
     
    -	b := New("local-grpc", "local-http", filemgr.NewManager(), nil)
    +	b := New("local-grpc", "local-http", "local-metrics", filemgr.NewManager(), nil)
     	rootCABytes, _ := getCombinedCertificateAuthority("", "")
     	rootCA := b.filemgr.BytesDataSource("ca.pem", rootCABytes).GetFilename()
     
    @@ -379,7 +379,7 @@ func Test_buildPolicyTransportSocket(t *testing.T) {
     
     func Test_buildCluster(t *testing.T) {
     	ctx := context.Background()
    -	b := New("local-grpc", "local-http", filemgr.NewManager(), nil)
    +	b := New("local-grpc", "local-http", "local-metrics", filemgr.NewManager(), nil)
     	rootCABytes, _ := getCombinedCertificateAuthority("", "")
     	rootCA := b.filemgr.BytesDataSource("ca.pem", rootCABytes).GetFilename()
     	o1 := config.NewDefaultOptions()
    @@ -858,7 +858,7 @@ func Test_bindConfig(t *testing.T) {
     	ctx, clearTimeout := context.WithTimeout(context.Background(), time.Second*10)
     	defer clearTimeout()
     
    -	b := New("local-grpc", "local-http", filemgr.NewManager(), nil)
    +	b := New("local-grpc", "local-http", "local-metrics", filemgr.NewManager(), nil)
     	t.Run("no bind config", func(t *testing.T) {
     		cluster, err := b.buildPolicyCluster(ctx, &config.Options{}, &config.Policy{
     			From: "https://from.example.com",
    
  • config/envoyconfig/listeners.go+1 1 modified
    @@ -486,7 +486,7 @@ func (b *Builder) buildMetricsHTTPConnectionManagerFilter() (*envoy_config_liste
     			Action: &envoy_config_route_v3.Route_Route{
     				Route: &envoy_config_route_v3.RouteAction{
     					ClusterSpecifier: &envoy_config_route_v3.RouteAction_Cluster{
    -						Cluster: "pomerium-control-plane-http",
    +						Cluster: "pomerium-control-plane-metrics",
     					},
     				},
     			},
    
  • config/envoyconfig/listeners_test.go+6 6 modified
    @@ -25,7 +25,7 @@ func Test_buildMetricsHTTPConnectionManagerFilter(t *testing.T) {
     	certFileName := filepath.Join(cacheDir, "pomerium", "envoy", "files", "tls-crt-354e49305a5a39414a545530374e58454e48334148524c4e324258463837364355564c4e4532464b54355139495547514a38.pem")
     	keyFileName := filepath.Join(cacheDir, "pomerium", "envoy", "files", "tls-key-3350415a38414e4e4a4655424e55393430474147324651433949384e485341334b5157364f424b4c5856365a545937383735.pem")
     
    -	b := New("local-grpc", "local-http", filemgr.NewManager(), nil)
    +	b := New("local-grpc", "local-http", "local-metrics", filemgr.NewManager(), nil)
     	li, err := b.buildMetricsListener(&config.Config{
     		Options: &config.Options{
     			MetricsAddr:           "127.0.0.1:9902",
    @@ -65,7 +65,7 @@ func Test_buildMetricsHTTPConnectionManagerFilter(t *testing.T) {
     								"prefix": "/"
     							},
     							"route": {
    -								"cluster": "pomerium-control-plane-http"
    +								"cluster": "pomerium-control-plane-metrics"
     							}
     						}]
     					}]
    @@ -108,7 +108,7 @@ func Test_buildMetricsHTTPConnectionManagerFilter(t *testing.T) {
     }
     
     func Test_buildMainHTTPConnectionManagerFilter(t *testing.T) {
    -	b := New("local-grpc", "local-http", nil, nil)
    +	b := New("local-grpc", "local-http", "local-metrics", nil, nil)
     
     	options := config.NewDefaultOptions()
     	options.SkipXffAppend = true
    @@ -523,7 +523,7 @@ func Test_buildMainHTTPConnectionManagerFilter(t *testing.T) {
     }
     
     func Test_buildDownstreamTLSContext(t *testing.T) {
    -	b := New("local-grpc", "local-http", filemgr.NewManager(), nil)
    +	b := New("local-grpc", "local-http", "local-metrics", filemgr.NewManager(), nil)
     
     	cacheDir, _ := os.UserCacheDir()
     	certFileName := filepath.Join(cacheDir, "pomerium", "envoy", "files", "tls-crt-354e49305a5a39414a545530374e58454e48334148524c4e324258463837364355564c4e4532464b54355139495547514a38.pem")
    @@ -805,7 +805,7 @@ func Test_hostMatchesDomain(t *testing.T) {
     }
     
     func Test_buildRouteConfiguration(t *testing.T) {
    -	b := New("local-grpc", "local-http", nil, nil)
    +	b := New("local-grpc", "local-http", "local-metrics", nil, nil)
     	virtualHosts := make([]*envoy_config_route_v3.VirtualHost, 10)
     	routeConfig, err := b.buildRouteConfiguration("test-route-configuration", virtualHosts)
     	require.NoError(t, err)
    @@ -815,7 +815,7 @@ func Test_buildRouteConfiguration(t *testing.T) {
     }
     
     func Test_requireProxyProtocol(t *testing.T) {
    -	b := New("local-grpc", "local-http", nil, nil)
    +	b := New("local-grpc", "local-http", "local-metrics", nil, nil)
     	t.Run("required", func(t *testing.T) {
     		li, err := b.buildMainListener(context.Background(), &config.Config{Options: &config.Options{
     			UseProxyProtocol: true,
    
  • config/envoyconfig/routes.go+20 52 modified
    @@ -57,51 +57,20 @@ func (b *Builder) buildPomeriumHTTPRoutes(options *config.Options, domain string
     		return nil, err
     	}
     	if !isFrontingAuthenticate {
    -		// enable ext_authz
    -		r, err := b.buildControlPlanePathRoute("/.pomerium/jwt", true)
    -		if err != nil {
    -			return nil, err
    -		}
    -		routes = append(routes, r)
    -
    -		// disable ext_authz and passthrough to proxy handlers
    -		r, err = b.buildControlPlanePathRoute("/ping", false)
    -		if err != nil {
    -			return nil, err
    -		}
    -		routes = append(routes, r)
    -		r, err = b.buildControlPlanePathRoute("/healthz", false)
    -		if err != nil {
    -			return nil, err
    -		}
    -		routes = append(routes, r)
    -		r, err = b.buildControlPlanePathRoute("/.pomerium", false)
    -		if err != nil {
    -			return nil, err
    -		}
    -		routes = append(routes, r)
    -		r, err = b.buildControlPlanePrefixRoute("/.pomerium/", false)
    -		if err != nil {
    -			return nil, err
    -		}
    -		routes = append(routes, r)
    -		r, err = b.buildControlPlanePathRoute("/.well-known/pomerium", false)
    -		if err != nil {
    -			return nil, err
    -		}
    -		routes = append(routes, r)
    -		r, err = b.buildControlPlanePrefixRoute("/.well-known/pomerium/", false)
    -		if err != nil {
    -			return nil, err
    -		}
    -		routes = append(routes, r)
    +		routes = append(routes,
    +			// enable ext_authz
    +			b.buildControlPlanePathRoute("/.pomerium/jwt", true),
    +			// disable ext_authz and passthrough to proxy handlers
    +			b.buildControlPlanePathRoute("/ping", false),
    +			b.buildControlPlanePathRoute("/healthz", false),
    +			b.buildControlPlanePathRoute("/.pomerium", false),
    +			b.buildControlPlanePrefixRoute("/.pomerium/", false),
    +			b.buildControlPlanePathRoute("/.well-known/pomerium", false),
    +			b.buildControlPlanePrefixRoute("/.well-known/pomerium/", false),
    +		)
     		// per #837, only add robots.txt if there are no unauthenticated routes
     		if !hasPublicPolicyMatchingURL(options, url.URL{Scheme: "https", Host: domain, Path: "/robots.txt"}) {
    -			r, err := b.buildControlPlanePathRoute("/robots.txt", false)
    -			if err != nil {
    -				return nil, err
    -			}
    -			routes = append(routes, r)
    +			routes = append(routes, b.buildControlPlanePathRoute("/robots.txt", false))
     		}
     	}
     	// if we're handling authentication, add the oauth2 callback url
    @@ -110,11 +79,10 @@ func (b *Builder) buildPomeriumHTTPRoutes(options *config.Options, domain string
     		return nil, err
     	}
     	if config.IsAuthenticate(options.Services) && hostMatchesDomain(authenticateURL, domain) {
    -		r, err := b.buildControlPlanePrefixRoute("/", false)
    -		if err != nil {
    -			return nil, err
    -		}
    -		routes = append(routes, r)
    +		routes = append(routes,
    +			b.buildControlPlanePathRoute(options.AuthenticateCallbackPath, false),
    +			b.buildControlPlanePathRoute("/", false),
    +		)
     	}
     	// if we're the proxy and this is the forward-auth url
     	forwardAuthURL, err := options.GetForwardAuthURL()
    @@ -196,7 +164,7 @@ func (b *Builder) buildControlPlanePathAndQueryRoute(path string, queryparams []
     	}, nil
     }
     
    -func (b *Builder) buildControlPlanePathRoute(path string, protected bool) (*envoy_config_route_v3.Route, error) {
    +func (b *Builder) buildControlPlanePathRoute(path string, protected bool) *envoy_config_route_v3.Route {
     	r := &envoy_config_route_v3.Route{
     		Name: "pomerium-path-" + path,
     		Match: &envoy_config_route_v3.RouteMatch{
    @@ -215,10 +183,10 @@ func (b *Builder) buildControlPlanePathRoute(path string, protected bool) (*envo
     			"envoy.filters.http.ext_authz": disableExtAuthz,
     		}
     	}
    -	return r, nil
    +	return r
     }
     
    -func (b *Builder) buildControlPlanePrefixRoute(prefix string, protected bool) (*envoy_config_route_v3.Route, error) {
    +func (b *Builder) buildControlPlanePrefixRoute(prefix string, protected bool) *envoy_config_route_v3.Route {
     	r := &envoy_config_route_v3.Route{
     		Name: "pomerium-prefix-" + prefix,
     		Match: &envoy_config_route_v3.RouteMatch{
    @@ -237,7 +205,7 @@ func (b *Builder) buildControlPlanePrefixRoute(prefix string, protected bool) (*
     			"envoy.filters.http.ext_authz": disableExtAuthz,
     		}
     	}
    -	return r, nil
    +	return r
     }
     
     // getClusterID returns a cluster ID
    
  • config/envoyconfig/routes_test.go+4 5 modified
    @@ -96,7 +96,8 @@ func Test_buildPomeriumHTTPRoutes(t *testing.T) {
     			`+routeString("path", "/.well-known/pomerium", false)+`,
     			`+routeString("prefix", "/.well-known/pomerium/", false)+`,
     			`+routeString("path", "/robots.txt", false)+`,
    -			`+routeString("prefix", "/", false)+`
    +			`+routeString("path", "/oauth2/callback", false)+`,
    +			`+routeString("path", "/", false)+`
     		]`, routes)
     	})
     	t.Run("proxy fronting authenticate", func(t *testing.T) {
    @@ -167,8 +168,7 @@ func Test_buildPomeriumHTTPRoutes(t *testing.T) {
     
     func Test_buildControlPlanePathRoute(t *testing.T) {
     	b := &Builder{filemgr: filemgr.NewManager()}
    -	route, err := b.buildControlPlanePathRoute("/hello/world", false)
    -	require.NoError(t, err)
    +	route := b.buildControlPlanePathRoute("/hello/world", false)
     	testutil.AssertProtoJSONEqual(t, `
     		{
     			"name": "pomerium-path-/hello/world",
    @@ -190,8 +190,7 @@ func Test_buildControlPlanePathRoute(t *testing.T) {
     
     func Test_buildControlPlanePrefixRoute(t *testing.T) {
     	b := &Builder{filemgr: filemgr.NewManager()}
    -	route, err := b.buildControlPlanePrefixRoute("/hello/world/", false)
    -	require.NoError(t, err)
    +	route := b.buildControlPlanePrefixRoute("/hello/world/", false)
     	testutil.AssertProtoJSONEqual(t, `
     		{
     			"name": "pomerium-prefix-/hello/world/",
    
  • config/metrics.go+25 15 modified
    @@ -3,6 +3,7 @@ package config
     import (
     	"context"
     	"net/http"
    +	"net/url"
     	"os"
     	"sync"
     
    @@ -16,12 +17,13 @@ import (
     
     // A MetricsManager manages metrics for a given configuration.
     type MetricsManager struct {
    -	mu             sync.RWMutex
    -	installationID string
    -	serviceName    string
    -	addr           string
    -	basicAuth      string
    -	handler        http.Handler
    +	mu                sync.RWMutex
    +	installationID    string
    +	serviceName       string
    +	addr              string
    +	basicAuth         string
    +	envoyAdminAddress string
    +	handler           http.Handler
     }
     
     // NewMetricsManager creates a new MetricsManager.
    @@ -46,8 +48,8 @@ func (mgr *MetricsManager) OnConfigChange(ctx context.Context, cfg *Config) {
     	mgr.mu.Lock()
     	defer mgr.mu.Unlock()
     
    -	mgr.updateInfo(cfg)
    -	mgr.updateServer(cfg)
    +	mgr.updateInfo(ctx, cfg)
    +	mgr.updateServer(ctx, cfg)
     }
     
     func (mgr *MetricsManager) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    @@ -61,42 +63,50 @@ func (mgr *MetricsManager) ServeHTTP(w http.ResponseWriter, r *http.Request) {
     	mgr.handler.ServeHTTP(w, r)
     }
     
    -func (mgr *MetricsManager) updateInfo(cfg *Config) {
    +func (mgr *MetricsManager) updateInfo(ctx context.Context, cfg *Config) {
     	serviceName := telemetry.ServiceName(cfg.Options.Services)
     	if serviceName == mgr.serviceName {
     		return
     	}
     
     	hostname, err := os.Hostname()
     	if err != nil {
    -		log.Error(context.TODO()).Err(err).Msg("telemetry/metrics: failed to get OS hostname")
    +		log.Error(ctx).Err(err).Msg("telemetry/metrics: failed to get OS hostname")
     		hostname = "__unknown__"
     	}
     
     	metrics.SetBuildInfo(serviceName, hostname, cfg.EnvoyVersion)
     	mgr.serviceName = serviceName
     }
     
    -func (mgr *MetricsManager) updateServer(cfg *Config) {
    +func (mgr *MetricsManager) updateServer(ctx context.Context, cfg *Config) {
     	if cfg.Options.MetricsAddr == mgr.addr &&
     		cfg.Options.MetricsBasicAuth == mgr.basicAuth &&
    -		cfg.Options.InstallationID == mgr.installationID {
    +		cfg.Options.InstallationID == mgr.installationID &&
    +		cfg.Options.EnvoyAdminAddress == mgr.envoyAdminAddress {
     		return
     	}
     
     	mgr.addr = cfg.Options.MetricsAddr
     	mgr.basicAuth = cfg.Options.MetricsBasicAuth
     	mgr.installationID = cfg.Options.InstallationID
    +	mgr.envoyAdminAddress = cfg.Options.EnvoyAdminAddress
     	mgr.handler = nil
     
     	if mgr.addr == "" {
    -		log.Info(context.TODO()).Msg("metrics: http server disabled")
    +		log.Info(ctx).Msg("metrics: http server disabled")
     		return
     	}
     
    -	handler, err := metrics.PrometheusHandler(EnvoyAdminURL, mgr.installationID)
    +	envoyURL, err := url.Parse("http://" + cfg.Options.EnvoyAdminAddress)
     	if err != nil {
    -		log.Error(context.TODO()).Err(err).Msg("metrics: failed to create prometheus handler")
    +		log.Error(ctx).Err(err).Msg("metrics: invalid envoy admin address, disabling")
    +		return
    +	}
    +
    +	handler, err := metrics.PrometheusHandler(envoyURL, mgr.installationID)
    +	if err != nil {
    +		log.Error(ctx).Err(err).Msg("metrics: failed to create prometheus handler")
     		return
     	}
     
    
  • config/options.go+0 3 modified
    @@ -49,9 +49,6 @@ const (
     // gRPC server, or is used for healthchecks (authorize only service)
     const DefaultAlternativeAddr = ":5443"
     
    -// EnvoyAdminURL indicates where the envoy control plane is listening
    -var EnvoyAdminURL = &url.URL{Host: "127.0.0.1:9901", Scheme: "http"}
    -
     // The randomSharedKey is used if no shared key is supplied in all-in-one mode.
     var randomSharedKey = cryptutil.NewBase64Key()
     
    
  • internal/cmd/pomerium/pomerium.go+2 0 modified
    @@ -86,6 +86,8 @@ func Run(ctx context.Context, configFile string) error {
     		Str("grpc-port", src.GetConfig().GRPCPort).
     		Str("http-port", src.GetConfig().HTTPPort).
     		Str("outbound-port", src.GetConfig().OutboundPort).
    +		Str("metrics-port", src.GetConfig().MetricsPort).
    +		Str("debug-port", src.GetConfig().DebugPort).
     		Msg("server started")
     
     	// create envoy server
    
  • internal/controlplane/http.go+6 6 modified
    @@ -49,12 +49,12 @@ func (srv *Server) addHTTPMiddleware() {
     	root.HandleFunc("/ping", httputil.HealthCheck)
     
     	// pprof
    -	root.Path("/debug/pprof/cmdline").HandlerFunc(pprof.Cmdline)
    -	root.Path("/debug/pprof/profile").HandlerFunc(pprof.Profile)
    -	root.Path("/debug/pprof/symbol").HandlerFunc(pprof.Symbol)
    -	root.Path("/debug/pprof/trace").HandlerFunc(pprof.Trace)
    -	root.PathPrefix("/debug/pprof/").HandlerFunc(pprof.Index)
    +	srv.DebugRouter.Path("/debug/pprof/cmdline").HandlerFunc(pprof.Cmdline)
    +	srv.DebugRouter.Path("/debug/pprof/profile").HandlerFunc(pprof.Profile)
    +	srv.DebugRouter.Path("/debug/pprof/symbol").HandlerFunc(pprof.Symbol)
    +	srv.DebugRouter.Path("/debug/pprof/trace").HandlerFunc(pprof.Trace)
    +	srv.DebugRouter.PathPrefix("/debug/pprof/").HandlerFunc(pprof.Index)
     
     	// metrics
    -	root.Handle("/metrics", srv.metricsMgr)
    +	srv.MetricsRouter.Handle("/metrics", srv.metricsMgr)
     }
    
  • internal/controlplane/server.go+59 23 modified
    @@ -50,11 +50,15 @@ func (avo *atomicVersionedConfig) Store(cfg versionedConfig) {
     
     // A Server is the control-plane gRPC and HTTP servers.
     type Server struct {
    -	GRPCListener net.Listener
    -	GRPCServer   *grpc.Server
    -	HTTPListener net.Listener
    -	HTTPRouter   *mux.Router
    -	Builder      *envoyconfig.Builder
    +	GRPCListener    net.Listener
    +	GRPCServer      *grpc.Server
    +	HTTPListener    net.Listener
    +	HTTPRouter      *mux.Router
    +	MetricsListener net.Listener
    +	MetricsRouter   *mux.Router
    +	DebugListener   net.Listener
    +	DebugRouter     *mux.Router
    +	Builder         *envoyconfig.Builder
     
     	currentConfig atomicVersionedConfig
     	name          string
    @@ -106,7 +110,25 @@ func NewServer(cfg *config.Config, metricsMgr *config.MetricsManager) (*Server,
     		_ = srv.GRPCListener.Close()
     		return nil, err
     	}
    +
    +	srv.MetricsListener, err = net.Listen("tcp4", net.JoinHostPort("127.0.0.1", cfg.MetricsPort))
    +	if err != nil {
    +		_ = srv.GRPCListener.Close()
    +		_ = srv.HTTPListener.Close()
    +		return nil, err
    +	}
    +
    +	srv.DebugListener, err = net.Listen("tcp4", net.JoinHostPort("127.0.0.1", cfg.DebugPort))
    +	if err != nil {
    +		_ = srv.GRPCListener.Close()
    +		_ = srv.HTTPListener.Close()
    +		_ = srv.DebugListener.Close()
    +		return nil, err
    +	}
    +
     	srv.HTTPRouter = mux.NewRouter()
    +	srv.DebugRouter = mux.NewRouter()
    +	srv.MetricsRouter = mux.NewRouter()
     	srv.addHTTPMiddleware()
     
     	srv.filemgr = filemgr.NewManager()
    @@ -115,6 +137,7 @@ func NewServer(cfg *config.Config, metricsMgr *config.MetricsManager) (*Server,
     	srv.Builder = envoyconfig.New(
     		srv.GRPCListener.Addr().String(),
     		srv.HTTPListener.Addr().String(),
    +		srv.MetricsListener.Addr().String(),
     		srv.filemgr,
     		srv.reproxy,
     	)
    @@ -175,28 +198,41 @@ func (srv *Server) Run(ctx context.Context) error {
     		return nil
     	})
     
    -	hsrv := (&http.Server{
    -		BaseContext: func(li net.Listener) context.Context {
    -			return ctx
    -		},
    -		Handler: srv.HTTPRouter,
    -	})
    +	for _, entry := range []struct {
    +		Name     string
    +		Listener net.Listener
    +		Handler  *mux.Router
    +	}{
    +		{"http", srv.HTTPListener, srv.HTTPRouter},
    +		{"debug", srv.DebugListener, srv.DebugRouter},
    +		{"metrics", srv.MetricsListener, srv.MetricsRouter},
    +	} {
    +		entry := entry
    +		hsrv := (&http.Server{
    +			BaseContext: func(li net.Listener) context.Context {
    +				return ctx
    +			},
    +			Handler: entry.Handler,
    +		})
     
    -	// start the HTTP server
    -	eg.Go(func() error {
    -		log.Info(ctx).Str("addr", srv.HTTPListener.Addr().String()).Msg("starting control-plane HTTP server")
    -		return hsrv.Serve(srv.HTTPListener)
    -	})
    +		// start the HTTP server
    +		eg.Go(func() error {
    +			log.Info(ctx).
    +				Str("addr", entry.Listener.Addr().String()).
    +				Msgf("starting control-plane %s server", entry.Name)
    +			return hsrv.Serve(entry.Listener)
    +		})
     
    -	// gracefully stop the HTTP server on context cancellation
    -	eg.Go(func() error {
    -		<-ctx.Done()
    +		// gracefully stop the HTTP server on context cancellation
    +		eg.Go(func() error {
    +			<-ctx.Done()
     
    -		ctx, cleanup := context.WithTimeout(ctx, time.Second*5)
    -		defer cleanup()
    +			ctx, cleanup := context.WithTimeout(ctx, time.Second*5)
    +			defer cleanup()
     
    -		return hsrv.Shutdown(ctx)
    -	})
    +			return hsrv.Shutdown(ctx)
    +		})
    +	}
     
     	return eg.Wait()
     }
    
  • internal/registry/reporter.go+4 0 modified
    @@ -66,6 +66,10 @@ func (r *Reporter) OnConfigChange(ctx context.Context, cfg *config.Config) {
     }
     
     func getReportedServices(cfg *config.Config) ([]*pb.Service, error) {
    +	if cfg.Options.MetricsAddr == "" {
    +		return nil, nil
    +	}
    +
     	mu, err := metricsURL(*cfg.Options)
     	if err != nil {
     		return nil, err
    

Vulnerability mechanics

Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

6

News mentions

0

No linked articles in our index yet.