Vulnerabilities

CORS Misconfigurations: The Silent Security Risk in Every SaaS App

CORS Misconfigurations: The Silent Security Risk in Every SaaS App

CORS (Cross-Origin Resource Sharing) is one of the most misunderstood security mechanisms on the web. Configure it wrong, and attackers can steal your users' data from any website.

How CORS Works (30-Second Version)

Browsers enforce the "Same-Origin Policy" — JavaScript on domain A can't read responses from domain B. CORS is the controlled exception.

When your frontend (app.example.com) makes an API call to your backend (api.example.com), the browser checks if the API explicitly allows requests from app.example.com.

The API signals this via the Access-Control-Allow-Origin header:

Access-Control-Allow-Origin: https://app.example.com

The 4 Most Dangerous CORS Misconfigurations

1. Wildcard Origin With Credentials

Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
Risk level: CRITICAL

This combination is actually blocked by browsers (they won't send cookies with wildcard origins). But some developers work around it by...

2. Reflecting the Origin Header

// DANGEROUS - reflects any origin
app.use((req, res, next) => {
  res.setHeader('Access-Control-Allow-Origin', req.headers.origin);
  res.setHeader('Access-Control-Allow-Credentials', 'true');
  next();
});
Risk level: CRITICAL

This effectively allows ANY website to make authenticated requests to your API. An attacker's site at evil.com can read your users' data, modify their accounts, or exfiltrate sensitive information.

The fix: Maintain an explicit allowlist:
const allowedOrigins = [
  'https://app.example.com',
  'https://staging.example.com'
];

app.use((req, res, next) => {
const origin = req.headers.origin;
if (allowedOrigins.includes(origin)) {
res.setHeader('Access-Control-Allow-Origin', origin);
res.setHeader('Access-Control-Allow-Credentials', 'true');
}
next();
});

3. Null Origin Allowed

Access-Control-Allow-Origin: null
Risk level: HIGH

The null origin can be triggered from sandboxed iframes, local file pages, and certain redirect sequences. If your API allows it, attackers can exploit it.

The fix: Never allow the null origin in production.

4. Overly Broad Subdomain Matching

// DANGEROUS - any subdomain matches
if (origin.endsWith('.example.com')) {
  res.setHeader('Access-Control-Allow-Origin', origin);
}
Risk level: MEDIUM-HIGH

If an attacker can create content on any subdomain (user-generated content, compromised blog, etc.), they can bypass your CORS protection.

The fix: Use exact matching or validate the full origin:
const allowedOrigins = new Set([
  'https://app.example.com',
  'https://admin.example.com'
]);

// Exact match only
if (allowedOrigins.has(origin)) { ... }

What TrustGate Checks

When you scan your application, TrustGate tests:

Each finding maps to OWASP A01:2021 (Broken Access Control) and A05:2021 (Security Misconfiguration).

The Bottom Line

CORS configuration should be:

  • Explicit — list every allowed origin

  • Minimal — only allow origins that need access

  • Tested — scan regularly, especially after deploys
  • Don't trust frameworks' default CORS settings. Verify them. Scan your app to find CORS issues in seconds.

    Check Your Security Posture

    Run a free scan and get a compliance-mapped report in seconds.

    Scan Your Site Free →