必须为 target="_blank" 显式添加 rel="noopener",否则新页面可通过 window.opener.location 劫持原页面;应使用 url 构造函数解析 hostname 判断内外链;动态生成链接时需确保 rel 同步设置;window.open() 需通过 features 参数传入 "noopener"。

target="_blank" 必须配 rel="noopener"
不加 rel="noopener" 的 target="_blank" 是实际可利用的安全漏洞,不是理论风险。新打开的页面能通过 window.opener.location 直接劫持原页面跳转——比如把用户正在操作的后台系统悄悄重定向到钓鱼页。
Chrome 88+ 虽默认隐式启用 noopener,但 Safari 和 Firefox 仍完全依赖显式声明。别赌兼容性,只要写 target="_blank",就同步写 rel="noopener"。
常见错误写法:rel="NOOPENER"(大小写敏感)、rel="no-opener"(连字符无效)、只写 rel="noreferrer"(旧版 Safari 不切断 window.opener)。
区分内部链接和外部链接不能靠字符串匹配
用 href.indexOf("https://example.com") 或正则硬判域名,会漏掉协议相对 URL(//cdn.example.com)、端口(:3000)、子域名(blog.example.com vs example.com),甚至被 URL 编码干扰(https%3A%2F%2Fexample.com)。
正确做法是用 URL 构造函数解析后比对 hostname:
const a = document.querySelector('a');
const url = new URL(a.href, location.href);
if (url.hostname !== location.hostname) {
a.target = '_blank';
a.rel = 'noopener';
}
这个方案天然支持:#section、/path、//host/path、带端口或查询参数的 URL,且不依赖 jQuery 或第三方库。
使用 PptxGenJS 和 Python 解析,将结构化的 HTML/CSS 幻灯片内容转换为原生、可编辑的 PowerPoint(.pptx)演示文稿。
动态生成链接时 rel 容易被忽略
服务端模板(Jinja/Twig)、CMS 富文本编辑器、Markdown 渲染器(如 marked)常自动加 target="_blank",却不补 rel。这类链接在 DevTools 里看不出异常,Lighthouse 也不一定扫出,但攻击者一点就生效。
检查要点:
- 输出 HTML 中每个
target="_blank"是否都有对应rel="noopener" - 若用 Markdown 库,确认它支持
rel白名单配置(例如marked的renderer.link钩子) - 服务端拼接链接时,避免只写
target而不校验rel
window.open() 不吃 rel 属性
rel 只对 HTML 中的 <a></a> 标签生效。用 JavaScript 主动调用 window.open(url, '_blank') 时,rel 完全无效。
安全写法是传入第三个参数(features 字符串)并显式加 noopener:
window.open(url, '_blank', 'noopener');
注意:window.open(url, '_blank', 'noopener,noreferrer') 在部分浏览器中可能被忽略 noreferrer;更可靠的方式是配合 rel="noopener noreferrer" 用 <a></a> 标签 + click() 模拟,或接受 referrer 泄露风险仅用 noopener。
真正难处理的是 SSR 环境下直接调用 window.open 会报 ReferenceError: window is not defined,必须做运行时判断或改用服务端重定向。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










