HTML输出必须用htmlspecialchars()显式指定ENT_QUOTES、'UTF-8'编码和false参数,前端JS转义不能替代服务端过滤,注释和隐藏元素中的敏感信息需彻底移除。

直接输出用户输入内容而不转义,99% 会触发 XSS;用 htmlspecialchars() 不加参数或错用 ENT_NOQUOTES,照样可能被绕过。
HTML 输出时必须用 htmlspecialchars() 并显式指定参数
很多开发者以为调用 htmlspecialchars($str) 就万事大吉,但默认只转义双引号(ENT_COMPAT),单引号仍可被用于闭合属性值,构成攻击链。比如:<input value='<script>alert(1)</script>'> 中的单引号未被转义,脚本就能执行。
- 始终显式传入
ENT_QUOTES:它同时转义单、双引号 - 必须指定编码,如
'UTF-8',否则在某些旧版 PHP 下可能因编码不匹配导致绕过 -
$double_encode设为false可避免重复转义(例如已含的内容再被处理成 <code>)
正确写法:htmlspecialchars($user_input, ENT_QUOTES, 'UTF-8', false)
不要依赖前端 JS 做 HTML 转义
前端用 textContent 或 innerText 赋值看似安全,但若后端把原始字符串拼进 HTML 模板(如 <div>{{ raw_html }}</div>),JS 层的防护完全失效。React 的 dangerouslySetInnerHTML、Vue 的 v-html 都是同理——它们不转义,只渲染。
立即学习“前端免费学习笔记(深入)”;
- HTML 内容必须在服务端完成转义,再交付给前端
- 前端只负责展示,不承担“净化”责任;JS 转义库(如 DOMPurify)仅作二次校验,不能替代服务端过滤
- 模板引擎选型优先用
html/template(Go)、Thymeleaf(Java)等自带自动转义机制的方案
注释和隐藏元素里也可能藏敏感信息
开发常把调试信息、API key、内部路径写在 HTML 注释(<!-- DEBUG: api_key=xxx -->)或 display:none 元素中,这些内容对爬虫和渗透测试者完全可见。
- 上线前必须移除所有
<!--开头的注释,尤其含变量、配置、错误堆栈的 - 不要用 CSS 隐藏敏感数据;要用服务端逻辑控制是否输出
- 检查
meta标签,如<meta name="generator" content="WordPress 6.8">会暴露技术栈,便于针对性攻击
真正难的不是记住哪个函数该加什么参数,而是每次拼接 HTML 时都下意识问一句:“这个变量来自哪?有没有被信任过?它现在是不是纯文本?”——漏掉一次,就可能让整页变炮台。



















