使用innerHTML时如何解决XSS漏洞?需保留HTML内容展示
解决innerHTML XSS漏洞的可行方案
一、正确使用成熟的HTML sanitization库
你之前尝试的sanitization没解决问题,大概率是库的配置或使用方式有误。推荐用经过安全验证的DOMPurify,用法简单直接:
- 先通过npm或CDN引入库
- 替换原有代码:
const sanitizedHTML = DOMPurify.sanitize(newInnerHTML); $(this).parent()[0].innerHTML = sanitizedHTML;
如果需要保留自定义标签/属性,可配置规则:
const config = { ADD_TAGS: ['my-custom-tag'], ADD_ATTR: ['data-custom'] }; const sanitizedHTML = DOMPurify.sanitize(newInnerHTML, config);
二、手动构建DOM元素(替代innerHTML)
不想用第三方库的话,可手动创建节点,精准控制允许的标签和属性,从根源规避XSS:
const parent = $(this).parent()[0]; parent.innerHTML = ''; // 清空原有内容 // 解析输入内容 const parser = new DOMParser(); const doc = parser.parseFromString(newInnerHTML, 'text/html'); const allowedTags = ['P', 'STRONG']; // 定义允许的标签 // 遍历节点,只保留安全内容 Array.from(doc.body.childNodes).forEach(node => { if (node.nodeType === Node.ELEMENT_NODE && allowedTags.includes(node.tagName)) { // 过滤属性,只保留允许的项 const allowedAttrs = ['class']; Array.from(node.attributes).forEach(attr => { if (!allowedAttrs.includes(attr.name)) node.removeAttribute(attr.name); }); parent.appendChild(node.cloneNode(true)); } else if (node.nodeType === Node.TEXT_NODE) { parent.appendChild(node.cloneNode(true)); } });
三、textContent结合指定元素创建
如果仅需支持少量特定标签(如加粗、换行),可拆分内容,用textContent处理文本部分,避免注入:
const parent = $(this).parent()[0]; parent.innerHTML = ''; // 示例:仅支持<strong>标签 const parts = newInnerHTML.split(/(<strong>|<\/strong>)/); parts.forEach(part => { if (part === '<strong>') { parent.appendChild(document.createElement('strong')); } else if (part === '</strong>') { // 无需额外操作 } else { const textNode = document.createTextNode(part); const lastChild = parent.lastChild; // 若最后一个元素是strong,将文本插入其中 lastChild?.tagName === 'STRONG' ? lastChild.appendChild(textNode) : parent.appendChild(textNode); } });
四、排查sanitization失效原因
如果之前的sanitization没生效,先检查这几点:
- 是否在sanitize后又修改了HTML,重新引入恶意代码
- 使用的sanitization库版本是否过时,存在漏洞或配置缺陷
- 是否在sanitize步骤前就混入了恶意代码
内容的提问来源于stack exchange,提问作者user1700650
相关产品推荐
相关产品推荐

