Setting an overly permissive Cross-Origin Resource Sharing (CORS) policy allows malicious websites to read responses from your application on behalf of authenticated users.

Why is this an issue?

Same-origin policy in browsers prevents JavaScript from making cross-origin HTTP requests to resources with a different origin (domain, protocol, or port). The Cross-Origin Resource Sharing (CORS) mechanism allows servers to relax this restriction by including Access-Control-Allow-Origin response headers that tell browsers which origins are permitted.

Setting the Access-Control-Allow-Origin header to a wildcard (*) or dynamically reflecting a user-supplied Origin header without validation completely disables same-origin protection for the affected resource.

What is the potential impact?

Sensitive data exposure

When CORS restrictions are disabled, a malicious website visited by an authenticated user can issue cross-origin requests to the vulnerable application and read the responses. This allows attackers to steal sensitive data accessible to the victim, such as account details, API keys, or private application data.

Account takeover

If the application is also configured with Access-Control-Allow-Credentials: true, the browser will include cookies and HTTP authentication headers in cross-origin requests. Attackers can then perform authenticated operations on behalf of the victim, potentially leading to full account takeover or unauthorized data modification.

How to fix it in Servlet

Set the Access-Control-Allow-Origin header to a specific trusted origin.

Code examples

Noncompliant code example

@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    resp.setHeader("Content-Type", "text/plain; charset=utf-8");
    resp.setHeader("Access-Control-Allow-Origin", "*"); // Noncompliant
    resp.setHeader("Access-Control-Allow-Credentials", "true");
    resp.setHeader("Access-Control-Allow-Methods", "GET");
    resp.getWriter().write("response");
}

Compliant solution

@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    resp.setHeader("Content-Type", "text/plain; charset=utf-8");
    resp.setHeader("Access-Control-Allow-Origin", "https://trustedwebsite.com");
    resp.setHeader("Access-Control-Allow-Credentials", "true");
    resp.setHeader("Access-Control-Allow-Methods", "GET");
    resp.getWriter().write("response");
}

How to fix it in Spring

Use Spring’s CORS configuration to restrict allowed origins to specific trusted domains, and validate user-supplied origins against an allow-list.

Code examples

Noncompliant code example

CrossOrigin annotation:

@CrossOrigin // Noncompliant
@RequestMapping("")
public class TestController {
    public String home(ModelMap model) {
        model.addAttribute("message", "ok ");
        return "view";
    }
}

cors.CorsConfiguration class:

CorsConfiguration config = new CorsConfiguration();
config.addAllowedOrigin("*"); // Noncompliant
config.applyPermitDefaultValues(); // Noncompliant

servlet.config.annotation.CorsRegistration:

class Insecure implements WebMvcConfigurer {
  @Override
  public void addCorsMappings(CorsRegistry registry) {
    registry.addMapping("/**")
      .allowedOrigins("*"); // Noncompliant
  }
}

User-controlled origin:

public ResponseEntity<String> userControlledOrigin(@RequestHeader("Origin") String origin) {
  HttpHeaders responseHeaders = new HttpHeaders();
  responseHeaders.add("Access-Control-Allow-Origin", origin); // Noncompliant

  return new ResponseEntity<>("content", responseHeaders, HttpStatus.CREATED);
}

Compliant solution

CrossOrigin annotation:

@CrossOrigin("https://trustedwebsite.com")
@RequestMapping("")
public class TestController {
    public String home(ModelMap model) {
        model.addAttribute("message", "ok ");
        return "view";
    }
}

cors.CorsConfiguration class:

CorsConfiguration config = new CorsConfiguration();
config.addAllowedOrigin("http://domain2.com");

servlet.config.annotation.CorsConfiguration:

class Safe implements WebMvcConfigurer {
  @Override
  public void addCorsMappings(CorsRegistry registry) {
    registry.addMapping("/**")
      .allowedOrigins("https://safe.com");
  }
}

User-controlled origin validated with an allow-list:

public ResponseEntity<String> userControlledOrigin(@RequestHeader("Origin") String origin) {
  HttpHeaders responseHeaders = new HttpHeaders();
  if (trustedOrigins.contains(origin)) {
    responseHeaders.add("Access-Control-Allow-Origin", origin);
  }

  return new ResponseEntity<>("content", responseHeaders, HttpStatus.CREATED);
}

Resources

Documentation

Standards