Having a permissive Cross-Origin Resource Sharing policy is security-sensitive. It has led in the past to the following vulnerabilities:
Same origin policy in browsers prevents, by default and for
security-reasons, a javascript frontend to perform a cross-origin HTTP request to a resource that has a different origin (domain, protocol, or port)
from its own. The requested target can append additional HTTP headers in response, called CORS, that act like directives for the browser and change the access control policy
/ relax the same origin policy.
Ask Yourself Whether
- You don’t trust the origin specified, example:
Access-Control-Allow-Origin: untrustedwebsite.com
.
- Access control policy is entirely disabled:
Access-Control-Allow-Origin: *
- Your access control policy is dynamically defined by a user-controlled input like
origin
header.
There is a risk if you answered yes to any of those questions.
Recommended Secure Coding Practices
- The
Access-Control-Allow-Origin
header should be set only for a trusted origin and for specific resources.
- Allow only selected, trusted domains in the
Access-Control-Allow-Origin
header. Prefer whitelisting domains over blacklisting or
allowing any domain (do not use * wildcard nor blindly return the Origin
header content without any checks).
Sensitive Code Example
nodejs http built-in module:
const http = require('http');
const srv = http.createServer((req, res) => {
res.writeHead(200, { 'Access-Control-Allow-Origin': '*' }); // Sensitive
res.end('ok');
});
srv.listen(3000);
Express.js framework with cors middleware:
const cors = require('cors');
let app1 = express();
app1.use(cors()); // Sensitive: by default origin is set to *
let corsOptions = {
origin: '*' // Sensitive
};
let app2 = express();
app2.use(cors(corsOptions));
User-controlled origin:
function (req, res) {
const origin = req.headers.origin;
res.setHeader('Access-Control-Allow-Origin', origin); // Sensitive
};
Compliant Solution
nodejs http built-in module:
const http = require('http');
const srv = http.createServer((req, res) => {
res.writeHead(200, { 'Access-Control-Allow-Origin': 'trustedwebsite.com' }); // Compliant
res.end('ok');
});
srv.listen(3000);
Express.js framework with cors middleware:
const cors = require('cors');
let corsOptions = {
origin: 'trustedwebsite.com' // Compliant
};
let app = express();
app.use(cors(corsOptions));
User-controlled origin validated with an allow-list:
function (req, res) {
const origin = req.headers.origin;
if (origin === 'trustedwebsite.com') {
res.setHeader('Access-Control-Allow-Origin', origin);
}
};
See