This is an automated email from the ASF dual-hosted git repository.

epugh pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/solr-mcp.git


The following commit(s) were added to refs/heads/main by this push:
     new 8eff997  fix(security): replace permissive CORS wildcard with explicit 
allowlist (#121)
8eff997 is described below

commit 8eff997e4038565a9be10647225056322d9a16d4
Author: Aditya Parikh <[email protected]>
AuthorDate: Fri May 8 17:01:09 2026 -0400

    fix(security): replace permissive CORS wildcard with explicit allowlist 
(#121)
    
    The HTTP CORS configuration used setAllowedOriginPatterns("*") with
    allowCredentials=true, which is Spring's escape hatch around the
    browser rule that wildcards can't be used with credentials (MDN CORS
    spec). Replace with the strict setAllowedOrigins API and a configurable
    allowlist that defaults to the MCP Inspector's local proxy port.
    
    Methods and headers also tightened to the explicit set used by the
    Streamable HTTP transport per the MCP specification, replacing
    "*" wildcards.
    
    Operators add additional origins via the MCP_CORS_ALLOWED_ORIGINS env
    var or the mcp.cors.allowed-origins property.
    
    Refs:
    - MDN CORS — Credentialed requests and wildcards
    - CWE-942: Permissive Cross-domain Policy with Untrusted Domains
    - OWASP HTML5 Security Cheat Sheet (CORS)
    
    Signed-off-by: adityamparikh <[email protected]>
    Co-authored-by: Claude Opus 4.7 (1M context) <[email protected]>
    Co-authored-by: Eric Pugh <[email protected]>
---
 .../server/security/HttpSecurityConfiguration.java    | 19 ++++++++++++++++---
 src/main/resources/application-http.properties        |  4 ++++
 2 files changed, 20 insertions(+), 3 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 61f5663..d42be30 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
@@ -39,6 +39,9 @@ class HttpSecurityConfiguration {
        @Value("${spring.security.oauth2.resourceserver.jwt.issuer-uri:}")
        private String issuerUrl;
 
+       @Value("${mcp.cors.allowed-origins}")
+       private List<String> allowedOrigins;
+
        @Bean
        @ConditionalOnProperty(name = "http.security.enabled", havingValue = 
"true", matchIfMissing = true)
        SecurityFilterChain securityFilterChain(HttpSecurity http) throws 
Exception {
@@ -80,9 +83,19 @@ class HttpSecurityConfiguration {
 
        public CorsConfigurationSource corsConfigurationSource() {
                CorsConfiguration configuration = new CorsConfiguration();
-               configuration.setAllowedOriginPatterns(List.of("*"));
-               configuration.setAllowedMethods(List.of("*"));
-               configuration.setAllowedHeaders(List.of("*"));
+               // Use the strict setAllowedOrigins API (not 
setAllowedOriginPatterns) so the
+               // browser-spec rule that wildcards cannot be combined with 
credentials is
+               // enforced.
+               // Origins are configurable via the mcp.cors.allowed-origins 
property
+               // (env: MCP_CORS_ALLOWED_ORIGINS) and default to the MCP 
Inspector's local
+               // proxy.
+               configuration.setAllowedOrigins(allowedOrigins);
+               // Only the HTTP methods used by the MCP Streamable HTTP 
transport.
+               configuration.setAllowedMethods(List.of("GET", "POST", 
"DELETE", "OPTIONS"));
+               // Only the headers the MCP specification requires for the 
Streamable HTTP
+               // transport.
+               configuration.setAllowedHeaders(
+                               List.of("Authorization", "Content-Type", 
"Mcp-Session-Id", "MCP-Protocol-Version", "Last-Event-ID"));
                configuration.setAllowCredentials(true);
 
                UrlBasedCorsConfigurationSource source = new 
UrlBasedCorsConfigurationSource();
diff --git a/src/main/resources/application-http.properties 
b/src/main/resources/application-http.properties
index 1364348..6a613b5 100644
--- a/src/main/resources/application-http.properties
+++ b/src/main/resources/application-http.properties
@@ -28,6 +28,10 @@ 
spring.security.oauth2.resourceserver.jwt.issuer-uri=${OAUTH2_ISSUER_URI:https:/
 # in any environment reachable from the network is unsafe; the MCP 
Authorization
 # specification requires HTTP-based MCP servers to authenticate.
 http.security.enabled=${HTTP_SECURITY_ENABLED:true}
+# Comma-separated list of allowed CORS origins for the MCP HTTP endpoint.
+# Defaults to MCP Inspector's local proxy. Add additional origins 
(browser-based
+# MCP clients, internal dashboards) as needed. Do NOT use "*" with credentials.
+mcp.cors.allowed-origins=${MCP_CORS_ALLOWED_ORIGINS:http://localhost:6274,http://127.0.0.1:6274}
 # observability
 
management.endpoints.web.exposure.include=health,sbom,metrics,info,loggers,prometheus
 # Enable @Observed annotation support for custom spans

Reply via email to