=====================================
XSS(跨站脚本攻击)长期占据 OWASP Top 10 的显眼位置。React 作为当前主流前端框架,凭借 JSX 的默认转义机制,在一定程度上降低了 XSS 的发生概率。但“降低”不等于“消除”。在实际项目中,开发者一旦绕过 React 的安全设计,或者在后端、第三方库、服务端渲染等环节出现疏漏,XSS 依然可以轻易得手。本文从 React 项目的实际场景出发,梳理常见风险点,并给出可落地的防御策略。
React 为什么不能完全避免 XSS
React 在渲染文本内容时,会将变量中的特殊字符进行转义。例如 {userInput} 写入 JSX,<script> 会被转义为 <script>,浏览器不会将其当作标签执行。这是 React 内置的第一道防线。
但问题在于,React 提供了多个“逃生舱口”,允许开发者直接操作 HTML。一旦使用不当,转义机制就形同虚设。此外,XSS 并不只发生在前端渲染阶段,后端接口返回的数据、URL 参数、服务端渲染的 HTML 拼接,都可能成为攻击入口。
React 项目中常见的 XSS 风险点
1. dangerouslySetInnerHTML
这是 React 中最典型的 XSS 入口。当需要渲染富文本、Markdown 转换后的 HTML 时,开发者往往会使用 dangerouslySetInnerHTML。如果传入的 HTML 字符串未经净化,攻击者可以注入 <img src=x onerror=alert(1)> 或 <script> 标签,直接执行任意脚本。
// 危险写法:直接渲染用户提交的 HTML
<div dangerouslySetInnerHTML={{ __html: userContent }} />
2. href 与 src 中的 javascript: 协议
React 不会对 href 或 src 属性的值做协议白名单校验。如果攻击者能够控制链接地址,可以构造 javascript:alert(document.cookie),用户点击后即触发脚本。
// 危险写法:用户可控的链接地址
<a href={userProvidedUrl}>点击查看</a>
3. 服务端渲染(SSR)中的字符串拼接
在 Next.js、Remix 等 SSR 框架中,如果开发者手动拼接 HTML 字符串返回给客户端,React 的转义机制不会介入。任何未经过滤的用户输入拼入模板,都会造成反射型或存储型 XSS。
4. 第三方组件与 Markdown 渲染
富文本编辑器、Markdown 渲染库、代码高亮组件等第三方依赖,如果配置不当或版本存在漏洞,也可能引入 XSS。例如某些 Markdown 解析器默认允许内联 HTML,攻击者可以通过 Markdown 注入脚本。
5. URL 参数与路由状态
从 location.search、location.hash 或路由参数中读取的数据,如果直接渲染到页面上,同样可能携带恶意脚本。这类风险在单页应用中尤为常见。
前端防御策略
1. 对富文本进行严格净化
如果必须使用 dangerouslySetInnerHTML,务必在渲染前使用 DOMPurify 等专业库对 HTML 进行净化。DOMPurify 会移除所有危险标签和属性,只保留安全的 HTML 子集。
import DOMPurify from 'dompurify';
const cleanHtml = DOMPurify.sanitize(userContent);
<div dangerouslySetInnerHTML={{ __html: cleanHtml }} />
同时,配置 DOMPurify 时明确允许的标签和属性白名单,避免过度放行。
2. 校验 URL 协议
对于用户可控的链接,渲染前检查协议是否为 http:、https:、mailto: 等安全协议。可以使用 new URL() 解析后判断 protocol 字段,拒绝 javascript:、data: 等危险协议。
function safeUrl(url) {
try {
const parsed = new URL(url, window.location.origin);
if (['http:', 'https:', 'mailto:'].includes(parsed.protocol)) {
return parsed.href;
}
} catch (e) {}
return '#';
}
3. 避免直接拼接 HTML
在 SSR 场景中,优先使用框架提供的模板引擎和转义机制,不要手动拼接 HTML 字符串。如果必须拼接,对每个变量使用 HTML 实体编码。
4. 设置 Content Security Policy(CSP)
CSP 是纵深防御的重要手段。通过 HTTP 响应头限制脚本来源,即使攻击者成功注入脚本,浏览器也会拒绝执行。推荐配置:
Content-Security-Policy: default-src 'self'; script-src 'self'; object-src 'none'; base-uri 'self';
在 React 项目中,避免使用 unsafe-inline 和 unsafe-eval。如果使用了 styled-components 等运行时样式库,可以通过 nonce 或 hash 方式兼容。
5. 谨慎选择第三方依赖
定期审计项目依赖,关注安全公告。对于 Markdown 渲染、富文本展示类库,确认其默认配置是否安全,必要时关闭内联 HTML 解析功能。
6. 对 Cookie 设置 HttpOnly
虽然这属于后端措施,但对前端防御 XSS 同样关键。将敏感 Cookie 标记为 HttpOnly,即使 XSS 成功执行,攻击者也无法通过 document.cookie 窃取会话凭证。
总结
React 的默认转义机制是一道有效但并非万能的防线。真正的安全需要开发者在每个数据流入点保持警惕:净化富文本、校验 URL、避免手动拼接 HTML、配置 CSP、审慎使用第三方库。XSS 防御不是一次性的工作,而是贯穿开发、测试、部署全流程的持续实践。只有将前端防御与后端过滤、CSP 策略、Cookie 安全属性结合起来,才能构建起真正可靠的纵深防御体系。
未经允许不得转载:任鹏个人博客 » React 项目中的 XSS 风险点与防御策略


朋友圈点赞图在线生成源码