我们都知道,React 元素是一个 plain object
:
js
let el = {
type: 'marquee',
props: {
bgcolor: '#ffa7c4',
children: 'hi',
},
key: null,
ref: null,
$$typeof: Symbol.for('react.element'),
}
如果你的服务器有允许用户存储任意 JSON 对象的漏洞,而前端需要一个字符串,这可能会发生一个问题:导致潜在的安全风险
js
// 服务端允许用户存储 JSON
let expectedTextButGotJSON = {
type: 'div',
props: {
dangerouslySetInnerHTML: {
__html: 'dangerous InnerHTML'
},
},
// ...
};
let message = { text: expectedTextButGotJSON };
然后在某段 JSX 中使用了它,攻击者就可以运行我们不期望的 html 代码:
js
// React 0.13 中有风险
<p>
{message.text}
</p>
但是 React 在之后的版本中使用了 Symbol 标记 React 元素:
js
let el = {
type: 'marquee',
props: {
bgcolor: '#ffa7c4',
children: 'hi',
},
key: null,
ref: null,
$$typeof: Symbol.for('react.element'),
}
因为 JSON 不支持 Symbol 类型。所以即使服务器存在用 JSON 作为文本返回安全漏洞,JSON 里也不包含 Symbol.for('react.element')。React 会检测 element.$$typeof,如果元素丢失或者无效,会拒绝处理该元素。