CORS Configuration.
Misconfigured CORS can let any website read your API responses
What does this check test?
Cross-Origin Resource Sharing (CORS) is a mechanism that uses HTTP headers (`Access-Control-Allow-Origin`, `Access-Control-Allow-Credentials`, `Access-Control-Allow-Methods`, etc.) to control which external origins can make requests to your API and read the responses. Browsers enforce the same-origin policy by default, blocking cross-origin requests unless the server explicitly permits them via CORS headers. A misconfigured CORS policy can inadvertently grant access to sensitive data from any website.
Why does it matter?
A wildcard `Access-Control-Allow-Origin: *` with `Access-Control-Allow-Credentials: true` (which browsers actually block, but variants of this misconfiguration exist) or dynamically reflecting the request's `Origin` header without validation can allow any malicious site to make authenticated requests to your API and read the responses. This means an attacker's page could read a user's account data, transaction history, or private messages. CORS misconfigurations are one of the most common API security issues and frequently appear in bug bounty reports.
Who is affected?
Any application that exposes APIs consumed by web frontends on different origins must configure CORS carefully. Single-page applications (SPAs) hosted on a different domain than their API backend are the most common use case. Internal APIs that should only be accessed by specific frontends must restrict their CORS origins explicitly. Public APIs that do not return user-specific data may use a wildcard, but APIs returning authenticated data must never do so.
Where does this apply?
CORS headers are set on API responses, typically in your web server configuration, API gateway, or application middleware. Check the `Access-Control-Allow-Origin` header in responses to cross-origin requests. Pay special attention to preflight (OPTIONS) responses. Test by making requests from a different origin and inspecting the response headers in browser DevTools under the Network tab.
How to fix it
Node.js / Express
const cors = require('cors');
const allowedOrigins = ['https://app.example.com', 'https://admin.example.com'];
app.use(cors({
origin: (origin, callback) => {
if (!origin || allowedOrigins.includes(origin)) {
callback(null, true);
} else {
callback(new Error('Not allowed by CORS'));
}
},
credentials: true,
methods: ['GET', 'POST', 'PUT', 'DELETE'],
allowedHeaders: ['Content-Type', 'Authorization']
})); Nginx
map $http_origin $cors_origin {
default '';
'https://app.example.com' $http_origin;
'https://admin.example.com' $http_origin;
}
server {
add_header Access-Control-Allow-Origin $cors_origin always;
add_header Access-Control-Allow-Credentials 'true' always;
add_header Access-Control-Allow-Methods 'GET, POST, PUT, DELETE' always;
} Django
# settings.py
INSTALLED_APPS = [..., 'corsheaders']
MIDDLEWARE = ['corsheaders.middleware.CorsMiddleware', ...]
CORS_ALLOWED_ORIGINS = [
'https://app.example.com',
'https://admin.example.com',
]
CORS_ALLOW_CREDENTIALS = True Flask
from flask_cors import CORS
CORS(app, origins=['https://app.example.com', 'https://admin.example.com'],
supports_credentials=True) Next.js
module.exports = {
async headers() {
return [{
source: '/api/(.*)',
headers: [
{ key: 'Access-Control-Allow-Origin', value: 'https://app.example.com' },
{ key: 'Access-Control-Allow-Methods', value: 'GET, POST, PUT, DELETE' },
{ key: 'Access-Control-Allow-Credentials', value: 'true' }
]
}];
}
}; Spring Boot
@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/api/**")
.allowedOrigins("https://app.example.com", "https://admin.example.com")
.allowedMethods("GET", "POST", "PUT", "DELETE")
.allowCredentials(true);
}
} References
- MDN: Cross-Origin Resource Sharing (CORS)
- OWASP: CORS Misconfiguration
- PortSwigger: CORS Vulnerabilities
AppVet checks CORS Configuration automatically
Run a free security scan and get a full report with actionable fixes, including a Fix with AI prompt you can paste into any coding tool.
Run Audit