CodeIgniter 4 中无 xss_clean,应使用 esc() 函数按上下文转义输出,配合 HTMLPurifier 处理富文本,并禁用不安全的全局 XSS 过滤。

CodeIgniter 框架本身不提供能“一劳永逸”防 XSS 的过滤函数,xss_clean 在 CI 4 中已被彻底移除,CI 3 的实现也早被官方标记为不安全。真正起作用的不是输入清洗,而是输出转义 + 上下文隔离 + CSP 配合。
CI 4 中别再找 xss_clean,它根本不存在
CI 4 的 Form_validation 规则里没有 xss_clean,Security 类也不再暴露该方法。试图在 CI 4 里调用 $this->security->xss_clean() 会直接抛出 Call to undefined method 错误。这不是配置问题,是设计移除——官方文档明确指出:“XSS cleaning is deprecated and removed.”
- CI 3 的
xss_clean本质是启发式标签剥离+简单正则,对现代绕过(如onerror=alert(1)、javascript:alert()、Unicode 零宽字符)完全无效 - 它还会破坏合法内容:比如用户提交的代码示例
<div class="example"> 可能被删成 <code>div class="example" - CI 4 替代方案是分层防护:输入验证走
filter_var或自定义规则,输出一律用esc(),富文本走 HTMLPurifier - HTML 内容用
esc($str, 'html')—— 转义、<code>>、&、"、' - JavaScript 字符串内嵌变量用
esc($str, 'js')—— 处理换行、单双引号、反斜杠,避免语法破坏 - 作为 HTML 属性值(如
title="= esc($title, 'html') ?>")必须用'html',不能用'attr'—— CI 4 没有'attr'类型,'html'已覆盖属性场景 - URL 参数值用
esc($url, 'url'),但更推荐rawurlencode()配合filter_var($url, FILTER_SANITIZE_URL) - JSON 请求体(
$this->request->getJSON()返回的对象不受影响) - 路由参数(
$this->uri->getSegment(3))、Header 值、上传文件名 - 任何已解析后的数据,比如从数据库读出再拼接的字符串
- 它还会把
2026-04-20T01:01:00Z这类 ISO 时间戳里的T和Z当作标签干掉,变成2026-04-2001:01:00 - 安装
ezyang/htmlpurifier:composer require ezyang/htmlpurifier - 配置白名单:只允许
p、br、strong、em、ul、ol、li,禁用style、on*事件、javascript:协议 - 注意:HTMLPurifier 处理的是完整 HTML 片段,不是纯文本,别把它和
esc()混用或叠加
esc() 是 CI 4 输出转义的唯一推荐方式
esc() 不是过滤器,是上下文感知的转义函数,必须显式调用,且类型选错等于白做。它不会修改原始数据,只在输出那一刻做最小化编码。
全局 $globalXSSFiltering = true 是危险幻觉
在 app/Config/App.php 里设 $globalXSSFiltering = true,会让 CI 4 对所有 $_GET、$_POST、$_COOKIE 值自动调用 strip_tags() + 基础控制字符清理。但它不处理:
这个开关只适合遗留系统临时兜底,绝不能当作 XSS 防护主力。
富文本场景必须用 HTMLPurifier,别硬套 esc()
如果业务真需要保留 <p></p>、<strong></strong>、<ul></ul> 等标签(如 CMS 编辑器),esc($html, 'html') 会把全部标签转成纯文本,失去语义。这时必须引入外部库:
最易被忽略的一点:哪怕用了 HTMLPurifier,输出到页面时仍要包裹在 <div>= $clean_html ?></div>,而不能写成 <div>= esc($clean_html, 'html') ?></div>——后者会二次转义,把 <p></p> 变成 <p>。


















