必须为所有跨域标签补rel="noopener noreferrer",否则目标页可通过window.opener劫持原页面;漏检高发于富文本、cms导入和用户粘贴链接;可用正则匹配非本站外链并检查是否缺失noopener。

怎么识别未加 rel 属性的外链
浏览器默认打开外链时,目标页面能通过 window.opener 访问原页面,存在钓鱼或跳转劫持风险。必须为所有跨域 <a></a> 标签补上 rel="noopener noreferrer"(noreferrer 可选,但建议加上以隐藏 referrer)。
常见漏检点:富文本编辑器生成的 HTML、CMS 后台批量导入内容、用户粘贴的原始链接。这些场景下 rel 很容易被忽略。
- 用正则快速筛查:
/<a>]*href=["']https?:\/\/(?!(?:localhost|127\.0\.0\.1|yourdomain\.com))/i</a>匹配非本站 HTTP(S) 链接 - 检查匹配到的
<a></a>是否缺失rel属性,或rel值不含noopener - 注意:若链接已带
rel="nofollow",需手动合并为rel="nofollow noopener noreferrer",不能覆盖
如何验证外部链接是否真的可访问
光有 rel 不够,死链会损害用户体验和 SEO。但直接在前端发起 fetch 会触发 CORS,且大量并发请求易被目标站限流或封 IP。
正确做法是后端代理验证,前端只负责标记和反馈。例如用 Node.js 的 axios.head() 或 Python 的 requests.head() 发起轻量请求,超时设为 3 秒,仅关注状态码:
-
200、301、302→ 视为有效 -
404、410、500、503→ 标记为“不可达” - 超时或连接拒绝 → 暂标为“验证失败”,不直接禁用,留人工复核余地
避免在编辑器中实时轮询验证,改用“保存前触发一次批量检测”更稳妥。
白名单机制怎么配置才不误杀
企业级系统常要求只允许特定域名外链,比如只准连 github.com 和 wikipedia.org。硬编码正则容易出错,尤其处理子域和路径时。
推荐用结构化白名单 + 精确匹配逻辑:
- 白名单条目写成对象:
{"host": "github.com", "allowSubdomain": true}或{"host": "api.example.com", "allowSubdomain": false} - 解析用户输入的 URL 时,用
new URL(input)提取hostname,再逐条比对白名单中的host - 若
allowSubdomain === true,则允许docs.github.com;否则只认精确匹配,www.github.com会被拒绝 - 禁止通配符开头的模糊匹配(如
*.com),防止绕过
为什么 inline event handler 是个隐蔽风险
看似只是加个 onclick="trackOutbound()",但它会绕过 CSP(内容安全策略),且执行上下文不受控。这类属性在 HTML 质量扫描中常被忽略,但实际危害比裸外链更大。
检测时不能只盯 <a></a>,还要扫所有含事件属性的标签:
- 匹配关键词:
onerror、onclick、onmouseover、onload(包括大小写变体) - 特别注意
<img src="x" onerror="...">这类利用加载失败触发的 XSS 入口 - 一旦发现,应直接剥离该属性,改用 JS 绑定(且绑定逻辑需走白名单校验)
真正难处理的是那些嵌套在 data-* 属性里、运行时拼接的事件调用——这已经超出静态检测范围,需要结合 DOM 渲染后行为分析。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











