在CORS策略中使用indexOf做域名校验是否存在安全风险?
CORS白名单校验安全问题解答
现有方案的安全性评估
你提到的示例代码本身不存在http://example1.com.evil.com这类域名绕过的风险:
- 代码中的
whitelist.indexOf(origin)是在白名单数组中匹配完整的origin字符串,浏览器发起跨域请求时自动携带的origin头是包含协议、域名、端口的完整地址,恶意构造的http://example1.com.evil.com和白名单内的http://example1.com是完全不同的字符串,匹配会直接失败,不会被放行。
只有当匹配逻辑被错误写为「在origin字符串中查找是否包含白名单子串」时,才会出现你担心的绕过问题,这类错误写法示例如下:
// 错误写法,存在恶意域名绕过风险 var corsOptions = { origin: function (origin, callback) { // 错误点:判断origin是否包含白名单子串,而非完全匹配 if (whitelist.some(allowedOrigin => origin.indexOf(allowedOrigin) !== -1)) { callback(null, true) } else { callback(new Error('Not allowed by CORS')) } } }
更严谨的优化方案
如果你的业务只需要放行固定的完整origin,直接使用cors包内置的数组匹配能力即可,不需要自定义origin校验函数,避免手写逻辑出错:
const whitelist = ['http://example1.com', 'http://example2.com'] const corsOptions = { origin: whitelist // 直接传数组,cors包内部会自动做安全的完全匹配 }
如果需要支持子域名通配(比如允许*.example1.com的所有子域名),推荐通过URL对象解析域名后再做校验,不要直接做字符串模糊匹配:
const rootDomainWhitelist = new Set(['example1.com', 'example2.com']) const corsOptions = { origin: function (origin, callback) { // 可根据业务需求决定是否放行无origin的同站请求 if (!origin) return callback(new Error('Not allowed by CORS')) try { const requestHost = new URL(origin).hostname const isAllowed = rootDomainWhitelist.has(requestHost) || Array.from(rootDomainWhitelist).some(domain => requestHost.endsWith(`.${domain}`)) callback(null, isAllowed) } catch (err) { // 非法origin直接拦截 callback(new Error('Not allowed by CORS')) } } }
注意:如果用正则做自定义匹配,必须加开头和结尾锚点,例如匹配
http://example1.com的正则应写为/^http:\/\/example1\.com$/,避免子串匹配漏洞。
内容的提问来源于stack exchange,提问作者Christopher Waugh
相关产品推荐
相关产品推荐

