ci4 xss防护必须显式调用esc()按上下文编码输出,禁用xss_clean和全局过滤;富文本需白名单过滤,csrf与xss须分层独立防护。

WordPress 和 CodeIgniter 4 是两类完全不同的技术栈,不能混用“WP内容防XSS”直接套到 CI4 上——CI4 没有 WordPress 那套 esc_html()、wp_kses_post() 或自动输出过滤机制。它的 XSS 防护逻辑是显式、上下文感知、零全局过滤的。所谓“重构方案”,核心不是改配置,而是改写法。
CI4 中必须放弃的三件事
别再找 xss_clean() 函数——它在 CI4 里根本不存在;别设 $globalXSSFiltering = true——它会无差别 strip_tags,毁掉 JSON、代码块、富文本;别幻想“一次清洗,到处安全”——输入不清洗,只在输出时按场景编码。
输出必须按上下文调用 esc(),错一个就失效
CI4 的 esc() 不是万能胶,它是分类型的“精准转义器”:
- 渲染在 HTML 正文中:用
esc($data, 'html')(如<?php echo esc($title, 'html'); ?>) - 写进
<script></script>或内联 JS 字符串:必须用esc($data, 'js'),否则");alert(1)//仍可执行 - 塞进 HTML 属性值(如
title="= esc($text, 'attr') ?>"):用'attr',它会处理双引号、单引号和等号 - 拼接 URL 参数或
href值:用esc($url, 'url'),防止javascript:alert(1)类协议注入 - 写进
style属性或内联 CSS:用esc($css, 'css'),避免expression(...)或url(javascript:...)
富文本不能靠 esc(),得用白名单过滤
如果用户通过编辑器提交含 <p></p>、<strong></strong> 的内容,esc($html, 'html') 会把所有标签转成实体,变成纯文本。这时该做的是:
- 禁用
esc(),改用白名单过滤,例如strip_tags($html, ['p', 'br', 'strong', 'em', 'ul', 'ol', 'li']) - 更稳妥的做法是集成 HTML Purifier,配置严格白名单 + 属性校验(如只允许
class,禁用onerror、style等危险属性) - 绝对不要对富文本字段做
unserialize()或eval()—— CVE-2020-15148 反序列化漏洞至今未彻底修复
CSRF 和 XSS 必须分开防,不能互相替代
开了 CSRF 保护 ≠ 防了 XSS。两者防护点完全不同:
- CSRF 防的是“别人伪造你的身份发请求”,靠令牌校验(表单里加
= csrf_field() ?>,AJAX 请求头带X-CSRF-TOKEN) - XSS 防的是“你的页面执行了别人的脚本”,靠输出编码 + CSP + 输入验证
- 即使启用了 CSRF,若模板中写了
= $comment ?>而没esc(),XSS 依然畅通无阻 - 建议搭配 Content-Security-Policy 响应头(如
default-src 'self'; script-src 'self'),从浏览器层拦截未授权脚本执行











