Why AI tools produce this: AI coding tools produce this regularly, typically when prompted for a shortcut or a quick fix.
Why this matters
A wildcard origin combined with allowCredentials = true tells the browser to send the victim's cookies and authorization headers to a response that any site can read, a cross-origin account-takeover primitive (CWE-942). Because browsers reject a literal * when credentials are allowed, addAllowedOriginPattern("*") exists specifically to re-enable this unsafe combination, so its very use is the smell.
Never pair a wildcard origin with credentials. List the exact trusted origins (setAllowedOrigins(List.of("https://app.example.com")) with setAllowCredentials(true)) or drop credentials if you genuinely need a public, anonymous API.
VULNERABLE
vulnerable.java
import org.springframework.web.bind.annotation.CrossOrigin;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RestController;import org.springframework.web.cors.CorsConfiguration;@RestControllerclass AccountController { // Annotation: wildcard origin together with credentials. // ruleid: auth.java.cors.credentialed-wildcard @CrossOrigin(origins = "*", allowCredentials = "true") @GetMapping("/me") String me() { return "account"; } // Programmatic: the origin-pattern wildcard API, which only exists to allow // `*` with credentials. CorsConfiguration config() { CorsConfiguration cfg = new CorsConfiguration(); // ruleid: auth.java.cors.credentialed-wildcard cfg.addAllowedOriginPattern("*"); cfg.setAllowCredentials(true); return cfg; }}
SAFE
safe.java
import java.util.List;import org.springframework.web.bind.annotation.CrossOrigin;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RestController;import org.springframework.web.cors.CorsConfiguration;@RestControllerclass AccountController { // Explicit trusted origin with credentials — the correct configuration. // ok: auth.java.cors.credentialed-wildcard @CrossOrigin(origins = "https://app.example.com", allowCredentials = "true") @GetMapping("/me") String me() { return "account"; } // True-negative trap: a wildcard origin WITHOUT credentials is a different // (and separately linted) concern, not a credentialed wildcard. // ok: auth.java.cors.credentialed-wildcard @CrossOrigin(origins = "*") @GetMapping("/public") String publicData() { return "public"; } // Programmatic config with an explicit allowlist and credentials. CorsConfiguration config() { CorsConfiguration cfg = new CorsConfiguration(); // ok: auth.java.cors.credentialed-wildcard cfg.setAllowedOrigins(List.of("https://app.example.com")); cfg.setAllowCredentials(true); return cfg; }}
Suppressing this rule
If a finding is a genuine false positive, scope the suppression to the exact line and leave a reason, never disable the rule project-wide. Disable directives are line-scoped by design.