target="_blank"不加rel="noopener noreferrer"就是安全漏洞,新页面可通过window.opener劫持原页、跳转钓鱼页或清空DOM;noopener强制opener为null防劫持,noreferrer阻止Referer泄露,二者缺一不可且须小写无空格。

target="_blank"不加rel="noopener noreferrer"就是安全漏洞
单独写 target="_blank" 等于主动把 window.opener 这把钥匙交给新页面。它能直接执行 window.opener.location.replace() 把你原来的页面跳转到钓鱼页,也能清空 DOM、触发卡顿——这不是理论风险,TikTok 2023 年真实被利用过。
必须同时加上:rel="noopener noreferrer"。其中:noopener 是核心,强制新页面的 window.opener 为 null;noreferrer 是补充,阻止 Referer 头泄露来源 URL。漏掉任意一个,防护就不成立。
-
rel="noopener"单独写够防劫持,但隐私和部分 API 鉴权可能出问题 -
rel="noreferrer"单独写不行——旧版 Safari(≤10.0)仍允许访问window.opener -
rel必须小写、无空格、无连字符:rel="NOOPENER"或rel="noopener noreferrer "(末尾空格)都无效
哪些地方最容易漏掉 rel 属性
手动写 HTML 时容易补上,但动态生成环节几乎全是盲区:
- 富文本编辑器输出(如 CKEditor、TinyMCE)默认不加
rel,导出的 HTML 直接裸奔 - CMS 或博客系统自动生成的外链(评论区、文章内嵌链接),常只过滤
href,不校验rel - Vue/React 中用
v-html或dangerouslySetInnerHTML渲染用户输入,target="_blank"可能被注入,但rel不会自动补 - 第三方组件库(如旧版 Ant Design 的
Link)默认不加rel,升级前需手动 patch -
window.open(url, "_blank")调用时没传'noopener'特性字符串,比如正确写法是window.open(url, "_blank", "noopener")
target 值写错等于白写,合法值只有五个
浏览器只认这五种 target 值:_self、_blank、_parent、_top 和自定义 framename。其他写法不会报错,但会静默降级为 _self(当前页跳转),且不触发 rel 生效逻辑。
将调研报告、方案对比、数据分析、需求梳理、会议纪要、设计说明、代码评审、学习笔记等任务产物输出为可在浏览器直接打开的单文件 HTML,替代 Markdown 作为最终交付物。Markdown 在信息密度、视觉清晰度和可分享性上已跟不上 AI 产物的丰富度,HTML 能同时承载排版、表格、SVG 等。
立即学习“前端免费学习笔记(深入)”;
-
target="blank"(漏下划线)→ 当作普通窗口名处理,因无同名窗口,最终在当前页跳转 -
target="_new"、target="_window"→ 非标准值,所有现代浏览器忽略 -
target="_BLANK"(大小写错误)→_blank才有效 -
target="myFrame "(末尾空格)→ 匹配失败,行为不一致(部分 fallback 到_self,部分到_blank)
iframe 场景下 target 行为更复杂
含 <iframe> 的页面里,target 是否生效高度依赖 sandbox 权限和上下文:
- 如果
<iframe sandbox>没加allow-scripts或allow-popups,target="_blank"会被静默忽略 -
<iframe name="myframe">+target="myframe"会导致链接在该 iframe 内跳转,不是新开页 - 跨域 iframe 中,部分浏览器可能因安全策略把
target="_blank"降级为_self -
target="_parent"和target="_top"在现代 SPA 中极少使用,误写成target="parent"(缺下划线)会触发非标准窗口复用逻辑,且没noopener保护,风险更高
真正难的是统一覆盖所有动态生成路径——服务端渲染、富文本解析、组件封装、第三方 SDK,每个环节都可能漏掉 rel="noopener noreferrer"。靠肉眼检查几乎无效,得用 Lighthouse 扫描,或正则匹配 <a[^>]*target=["']_blank["'][^>]*> 并验证是否含 rel=["'].*noopener。


















