JavaScript无法单靠函数自动防御XSS,必须区分上下文、严格转义、禁用危险API:innerHTML/outerHTML、document.write、eval、setTimeout/setInterval传字符串、location跳转含javascript:、new Function均可能触发XSS。

JavaScript 中无法靠单个函数“自动”防御 XSS,关键在于区分上下文、严格转义、避免危险 API。
哪些操作会直接触发 XSS
以下行为只要输入未过滤,就可能执行恶意脚本:
-
innerHTML、outerHTML赋值含用户数据的字符串 -
document.write()或document.writeln()写入未处理内容 -
eval()、setTimeout(string, ...)、setInterval(string, ...)执行拼接的字符串 -
location.href、location.assign()跳转到拼接的 URL(尤其含javascript:伪协议) - 用
new Function(...)动态构造函数
不同上下文要用不同的转义方式
HTML 内容、HTML 属性、URL、JS 字符串,各自有独立的转义规则。混用等于白做。
- 插入 HTML 内容(如
div.innerHTML = ...):必须对、>、&、"、'做 HTML 实体编码,推荐用DOMPurify.sanitize()(而非仅转义) - 写入 HTML 属性(如
el.setAttribute('title', userText)):需先做 HTML 实体编码,且属性值必须用引号包裹(单/双皆可),避免闭合失败 - 拼入 URL(如
a.href = '/search?q=' + userInput):必须用encodeURIComponent(),不能用encodeURI()(后者不编码/、?等) - 嵌入 JS 字符串(如
console.log('${userInput}')):需用 JSON 序列化——JSON.stringify(userInput),它会正确处理引号、反斜杠和控制字符
哪些“看似安全”的做法其实很危险
开发者常误以为做了防护,实际仍可绕过:
动态WEB网站中的PHP和MySQL详细反映实际程序的需求,仔细地探讨外部数据的验证(例如信用卡卡号的格式)、用户登录以及如何使用模板建立网页的标准外观。动态WEB网站中的PHP和MySQL的内容不仅仅是这些。书中还提到如何串联JavaScript与PHP让用户操作时更快、更方便。还有正确处理用户输入错误的方法,让网站看起来更专业。另外还引入大量来自PEAR外挂函数库的强大功能,对常用的、强大的包
立即学习“Java免费学习笔记(深入)”;
- 只过滤
标签:攻击者可用或 - 用正则替换
javascript::可绕过为javascript:、JaVaScRiPt:、换行或空格分隔 - 服务端转义后前端再拼接:若前端又用
innerHTML插入,服务端转义可能被二次解释,应由前端在对应上下文做最终转义 - 信任
textContent就万事大吉:它确实防 XSS,但若后续又取textContent拼进innerHTML,风险重现
推荐的最小可行防护组合
不依赖框架时,优先采用“上下文感知 + 白名单净化”:
- 所有动态插入 HTML 的场景,用
DOMPurify.sanitize(htmlString, {ALLOWED_TAGS: ['b','i','p'], ALLOWED_ATTR: ['class']})—— 不要自己写过滤逻辑 - 纯文本渲染一律用
textContent或innerText(注意两者差异:innerText受 CSS 影响,textContent更可靠) - 服务端返回结构化数据(如 JSON),前端用
JSON.parse()消费,避免解析 HTML 片段 - 模板中避免拼接,改用原生
template+content.cloneNode(true)或document.createElement()构建节点
最易被忽略的是事件处理器和 URL 构造:哪怕用了 DOMPurify,如果把用户输入直接塞进 onclick 属性或 location.href,依然会触发 XSS。上下文永远比库更重要。










