v0.14 is out: a mobile auth pack for Swift/iOS and Android, catching insecure token storage, cleartext traffic, and OAuth in embedded WebViews. Read more →
HIGH AI PREVALENCE: MEDIUM auth.java.cors.credentialed-wildcard

CORS is configured to allow any origin together with credentials.

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;

@RestController
class 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;

@RestController
class 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.

// oauthlint-disable-next-line auth.java.cors.credentialed-wildcard -- <reason>

References

https://docs.spring.io/spring-framework/reference/web/webmvc-cors.html ↗https://portswigger.net/web-security/cors ↗https://cwe.mitre.org/data/definitions/942.html ↗