XSS漏洞本质是攻击者注入恶意脚本,因服务端未过滤或转义用户输入,导致浏览器直接执行。常见类型有反射型、存储型和DOM型,危害包括窃取Cookie、会话劫持等,防御须结合输入验证、输出编码、CSP及白名单HTML解析器。

textarea 值提交前不做任何过滤,等于默认放行 XSS
用户在 <textarea></textarea> 里粘贴一段带 <script></script> 或 <img src="x" onerror="alert(1)" alt="HTML表格内文本域内容安全过滤方法" > 的 HTML,浏览器不会拦截——它只管把原始字符串发出去。前端 JS 若没监听 submit 事件并调用 event.preventDefault(),后端收到的就是原样恶意内容。
常见错误包括:
– 以为 pattern 或 required 能拦住 HTML 标签
– 在 input 事件里改了 value,但提交时没阻止默认行为
– 对富文本字段用了 htmlspecialchars() 后直接入库,结果加粗、链接全变源码
- 必须用
addEventListener('submit', ...)拦截,不能依赖内联onsubmit - 过滤后要显式调用
this.submit(),否则仍发原始值 - 若字段允许简单格式(如粗体、链接),
textarea内容本质已是 HTML,不能当纯文本处理
后端入库前必须用白名单解析器,不是转义函数
htmlspecialchars() 和 strip_tags() 都不能用于 <textarea></textarea> 提交的富文本。前者把所有标签变成文本,后者留着 onclick 属性不删——两者都不解析 DOM,也校验不了 href="javascript:" 这类协议。
真正有效的只有白名单解析器:
– PHP 用 HTMLPurifier,配 HTML.Allowed = 'a[href|title],strong,em,p,br,ul,ol,li,img[src|alt]'
– Python 用 bleach.clean(),传 tags=['a','p'], attributes={'a': ['href']}, protocols=['https','http']
– Node.js 用 sanitize-html,设 allowedTags 和 allowedAttributes 并启用 disallowedTagsMode: 'recursiveEscape'
立即学习“前端免费学习笔记(深入)”;
- 禁用宽松模式:
HTMLPurifier_Config::createDefault()默认太松,必须手动收紧 - URI 协议必须显式限定,漏掉
'mailto'可能导致邮箱链接失效,漏掉限制则data:可注入 - 别在存储和渲染时各净化一次,重复处理会让
©变成©
表格内嵌 textarea 的特殊风险:多层上下文混用
HTML 表格本身不是安全边界。当 <textarea></textarea> 放在 <td> 里,且该表格又通过 JS 动态插入或由模板引擎渲染时,容易出现三重上下文错位:<br>– 输入是 HTML 字符串<br>– 表格单元格是 HTML 上下文<br>– 最终渲染可能进 <code>innerHTML、v-html 或 dangerouslySetInnerHTML
此时最常踩的坑:
– 把后端返回的已净化 HTML 直接塞进 td.innerHTML,看似安全,实则若前端再拼接其他变量,就可能触发二次注入
– 在 Vue 中用 v-html="item.content",却没确认 item.content 是经 HTMLPurifier 处理过的最终值,而是前端临时 sanitize 的中间结果
- 服务端返回的字段名要明确区分:比如
content_html(已净化) vscontent_raw(原始) - 前端渲染时,只信任带
_html后缀的字段;其余一律过一遍DOMPurify.sanitize()再用 - 表格列若支持排序/搜索,对
content_html做关键词高亮时,必须先剥离标签再匹配,否则正则会崩
DOMPurify 只能在 submit 时轻量跑一次,别在 input 里实时调
有人想在 input 事件里对 textarea.value 实时调 DOMPurify.sanitize(),这会导致两个问题:
– 输入中文或长段落时明显卡顿,尤其移动端
– 光标频繁跳到开头,破坏编辑体验
正确做法是仅在表单提交瞬间做一次:
– 用户点“保存”或按 Ctrl+Enter 时触发
– 用轻量配置(如只开 ALLOWED_TAGS,关掉 CSS 处理)
– 结果仅用于页面内预览,原始值仍发给后端
- 预览用的
DOMPurify.sanitize()不必和后端配置完全一致,但禁止标签(FORBID_TAGS)必须严格对齐 - 别用
keydown或paste替代input——前者漏掉右键粘贴、语音输入、拖放文本 - 如果表格支持行内编辑,每行
textarea提交前都得单独走这套流程,不能共用一个事件监听器
<textarea></textarea> 看似普通,但它承载的是未经解析的原始 HTML 字符串。安全的关键不在“怎么显示”,而在“谁有权决定哪些标签能活下来”——这个决定只能由后端白名单解析器在入库前做出,且必须与前端渲染时的信任边界完全对齐。



















