Cors Wildcard in Spring Boot with Bearer Tokens
Cors Wildcard in Spring Boot with Bearer Tokens — how this specific combination creates or exposes the vulnerability
A CORS wildcard (allowedOrigins = "*") combined with bearer token authentication in Spring Boot can unintentionally expose protected endpoints to unauthorized origins. When an endpoint validates bearer tokens but also permits any origin via a wildcard, an attacker website can make authenticated requests on behalf of a user using their valid token. The browser enforces CORS for cross-origin requests and will include cookies and Authorization headers when allowed, enabling a privileged request to be initiated from an untrusted site if the user is authenticated.
Spring Boot’s CORS configuration applies before Spring Security’s authorization filters. If allowedOrigins = "*" is set and credentials are not explicitly prohibited, the browser may still send the Authorization header for simple requests or preflighted requests, depending on how the server responds. With a wildcard, the server signals that any origin is acceptable, which can encourage browsers to include credentials when the endpoint also requires authentication. This mismatch allows an attacker to craft a page that calls the vulnerable endpoint using the victim’s token, leading to unauthorized actions or data exposure.
This combination is particularly risky for state-changing methods (POST, PUT, DELETE) and token-based flows where the token is passed in the Authorization header. Even if the server validates the token, the browser’s CORS behavior can permit a malicious origin to participate in the request/response cycle. Attack patterns include CSRF-like scenarios where an authenticated user is tricked into triggering cross-origin API calls, or token leakage through exposed responses if the wildcard is overly permissive.
For example, consider a Spring Boot controller that requires a Bearer token but allows all origins. An attacker’s site can perform authenticated API calls via JavaScript fetch if the browser includes the Authorization header. The server validates the token but sees the request as originating from an allowed wildcard domain, which can lead to unauthorized operations without proper origin checks.
Bearer Tokens-Specific Remediation in Spring Boot — concrete code fixes
Remediation centers on tightening CORS rules and ensuring token validation is coupled with origin verification. Avoid wildcard origins when authentication is required. Instead, specify exact origins and configure Spring Security to validate the Authorization header while rejecting requests from untrusted sources.
Below is a secure Spring Boot configuration that restricts CORS to known origins and requires Bearer token validation. It uses a WebSecurityConfigurerAdapter (for Spring Boot 2) or a SecurityFilterChain bean (for Spring Boot 3) and demonstrates how to enforce origin-based checks alongside bearer token validation.
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.cors(cors -> cors.configurationSource(request -> {
CorsConfiguration config = new CorsConfiguration();
config.setAllowedOrigins(List.of("https://trusted.example.com", "https://app.example.com"));
config.setAllowedMethods(List.of("GET", "POST", "PUT", "DELETE", "OPTIONS"));
config.setAllowedHeaders(List.of("Authorization", "Content-Type"));
config.setExposedHeaders(List.of("X-Request-ID"));
config.setAllowCredentials(true);
return config;
}))
.authorizeHttpRequests(auth -> auth
.requestMatchers("/public/**").permitAll()
.anyRequest().authenticated()
)
.oauth2ResourceServer(OAuth2ResourceServerConfigurer::jwt);
return http.build();
}
}
If you use a legacy style with WebSecurityConfigurerAdapter, the approach is similar but uses overridden methods:
@Configuration
@EnableWebSecurity
public class LegacySecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.cors(cors -> cors.configurationSource(request -> {
CorsConfiguration config = new CorsConfiguration();
config.setAllowedOrigins(List.of("https://trusted.example.com"));
config.setAllowedMethods(List.of("GET", "POST"));
config.setAllowedHeaders(List.of("Authorization"));
config.setAllowCredentials(true);
return config;
}))
.authorizeRequests()
.antMatchers("/public/**").permitAll()
.anyRequest().authenticated()
.and()
.oauth2ResourceServer().jwt();
}
}
Additionally, validate tokens explicitly for sensitive endpoints and reject requests with missing or malformed Authorization headers. Ensure that CORS configuration does not rely on dynamic origins derived from request headers, which can reintroduce wildcard-like behavior.
When integrating third-party identity providers, pin allowed origins to known domains and avoid reflecting the Origin header into Access-Control-Allow-Origin without strict validation. Combine these measures with rate limiting and token binding to reduce abuse surfaces.
Related CWEs: dataExposure
| CWE ID | Name | Severity |
|---|---|---|
| CWE-200 | Exposure of Sensitive Information | HIGH |
| CWE-209 | Error Information Disclosure | MEDIUM |
| CWE-213 | Exposure of Sensitive Information Due to Incompatible Policies | HIGH |
| CWE-215 | Insertion of Sensitive Information Into Debugging Code | MEDIUM |
| CWE-312 | Cleartext Storage of Sensitive Information | HIGH |
| CWE-359 | Exposure of Private Personal Information (PII) | HIGH |
| CWE-522 | Insufficiently Protected Credentials | CRITICAL |
| CWE-532 | Insertion of Sensitive Information into Log File | MEDIUM |
| CWE-538 | Insertion of Sensitive Information into Externally-Accessible File | HIGH |
| CWE-540 | Inclusion of Sensitive Information in Source Code | HIGH |
Frequently Asked Questions
Does allowing credentials with a CORS wildcard increase risk with Bearer tokens?
allowedOrigins = "*" and setAllowCredentials(true) are both set, browsers may send Authorization headers to any origin, bypassing intended restrictions. Specify exact origins instead.