JavaScript协议链接也会触发XSS吗?

Mr-红佑 阅读 34

我在做富文本展示功能,用户输入的内容里可能包含超链接。我过滤了标签,但发现如果链接是javascript:alert(1)这种形式,点击后还是会执行代码,这算XSS漏洞吗?

我试过用正则匹配href属性,但总觉得不够稳妥。有没有更可靠的方案?比如只允许httphttps开头的链接?

下面是我目前处理链接的代码:

function sanitizeHref(href) {
  if (!href) return '#';
  // 简单过滤 javascript: 协议
  if (href.trim().toLowerCase().startsWith('javascript:')) {
    return '#';
  }
  return href;
}
我来解答 赞 16 收藏
二维码
手机扫码查看
2 条解答
艺茹 ☘︎
你遇到的问题确实属于XSS漏洞的一种。简单地用正则匹配是不够的,因为攻击者可以绕过这些简单的检查,比如使用不同的编码方式或者大小写组合来避开检测。

更可靠的方法是只允许http或https开头的链接。这样可以大大降低风险,因为其他协议基本不需要在用户生成的内容中使用。

你可以修改你的函数如下:

function sanitizeHref(href) {
if (!href) return '#';
// 只允许http或https开头的链接
const allowedProtocols = ['http:', 'https:'];
if (!allowedProtocols.some(protocol => href.toLowerCase().startsWith(protocol))) {
return '#';
}
return href;
}


这样处理效率更高,也能更可靠地防止XSS攻击。别忘了对其他可能的注入点也进行类似的处理哦。
点赞
2026-03-21 08:06
Top丶培珍
这绝对是 XSS 漏洞,你现在的正则太天真了,攻击者可以用 java script:javanscript: 或者 data:text/html 等各种姿势绕过。

白名单才是正解,只允许已知安全的协议:

function sanitizeHref(href) {
if (!href) return '#';

// 干掉所有空白和不可见字符,防止绕过
const normalized = href.replace(/[su0000-u001f]+/g, '');

// 白名单协议
const allowedProtocols = ['http', 'https', 'mailto'];

const match = normalized.match(/^([a-zA-Z][a-zA-Z0-9+.-]*):/);
if (match && !allowedProtocols.includes(match[1].toLowerCase())) {
return '#';
}

return href;
}


检查一下你的场景,如果是富文本整体清洗,直接上 DOMPurify 这种成熟库,别自己造轮子,XSS 的坑比你想象的多。
点赞
2026-03-02 11:00