From 289fc0c887189d86515f5c8c48aaabc78e272dc3 Mon Sep 17 00:00:00 2001 From: adityamparikh Date: Fri, 8 May 2026 17:06:21 -0400 Subject: [PATCH] fix(security): require authentication for actuator endpoints other than health The secured filter chain matched /actuator and /actuator/* with permitAll, exposing the entire actuator surface anonymously even when http.security.enabled=true (sbom, loggers, prometheus, metrics, info). Tighten the matchers so /actuator/health stays anonymously reachable for load balancers and orchestrators, while everything else under /actuator requires an authenticated principal. Only relevant when http.security.enabled=true; the unsecured filter chain is unchanged. Signed-off-by: adityamparikh --- .../security/HttpSecurityConfiguration.java | 23 ++++++++++++------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/src/main/java/org/apache/solr/mcp/server/security/HttpSecurityConfiguration.java b/src/main/java/org/apache/solr/mcp/server/security/HttpSecurityConfiguration.java index d42be30..86f7bf2 100644 --- a/src/main/java/org/apache/solr/mcp/server/security/HttpSecurityConfiguration.java +++ b/src/main/java/org/apache/solr/mcp/server/security/HttpSecurityConfiguration.java @@ -45,14 +45,21 @@ class HttpSecurityConfiguration { @Bean @ConditionalOnProperty(name = "http.security.enabled", havingValue = "true", matchIfMissing = true) SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { - return http - // ⬇️ Open every request on the server - .authorizeHttpRequests(auth -> { - auth.requestMatchers("/actuator").permitAll(); - auth.requestMatchers("/actuator/*").permitAll(); - auth.requestMatchers("/mcp").permitAll(); - auth.anyRequest().authenticated(); - }) + return http.authorizeHttpRequests(auth -> { + // Liveness/readiness probes need anonymous access for load + // balancers and orchestrators. All other actuator endpoints + // (loggers, sbom, metrics, prometheus, info) require auth so + // that an unauthenticated caller cannot read the dependency + // tree, scrape metrics that map the tool surface, or — if + // path-matcher semantics ever shift — change log levels. + auth.requestMatchers("/actuator/health").permitAll(); + auth.requestMatchers("/actuator", "/actuator/**").authenticated(); + // /mcp is gated by @PreAuthorize on individual @McpTool + // methods, matching the spring-ai-community/mcp-security + // "secured tools" sample pattern. + auth.requestMatchers("/mcp").permitAll(); + auth.anyRequest().authenticated(); + }) // Configure OAuth2 on the MCP server. // // resourcePath: declares "/mcp" as the canonical resource indicator