不能用 object.seal 防御 props 注入,因 props 是只读设计约定而非安全机制;seal 无法阻止属性值修改,且 react 每次渲染可能新建 props 对象;应通过输入校验、类型检查、dom 净化等源头防护。

不能也不应该用 Object.seal 锁定 React 组件的 props 对象来“防御非法注入”。
React 的 props 本就是只读契约,不是运行时防护机制
React 官方明确将 props 定义为只读(read-only)——这不是一个安全边界,而是一种设计约定和开发约束。组件内部修改 this.props(类组件)或直接赋值 props.xxx = ...(函数组件中解构前)会触发开发环境警告,但不会抛错,更不构成“注入防护”。Object.seal 只能防止新增/删除属性、冻结属性描述符,无法阻止已有属性的值被重新赋值(除非该属性本身是 writable: false),对普通对象属性的修改完全无效。
seal 在 props 上实际无效且干扰正常开发
React 内部并不复用或长期持有用户传入的 props 对象;每次渲染都可能生成新对象(尤其在 JSX 中使用字面量或内联对象时)。即使你在组件开头手动调用:
Object.seal(props); // ❌ 无意义:props 是临时对象,且 seal 不防 value 修改
这既不能阻止父组件下次传入不同 props,也无法防止组件内部意外修改(比如误写 props.count++ —— 这行代码在非严格模式下静默失败,在严格模式下才报错,但错误根源是代码 bug,不是“注入”)。
真正需要防范的是数据来源与执行上下文
所谓“非法注入”,通常指:
- 来自不可信输入(如 URL 参数、localStorage、用户提交内容)的数据未经校验直接用于渲染或执行
- 动态拼接 JSX 或使用 dangerouslySetInnerHTML 时未转义
- 将用户输入当作函数名、键名或模块路径动态调用
应对方式应是:
- 对所有外部输入做白名单校验或结构化解析(例如用
zod或yup验证 props 类型) - 避免动态 key 访问(
obj[untrustedKey])、eval、Function构造函数、import()带变量路径 - 渲染 HTML 片段时始终使用
DOMPurify等库净化 - 利用 TypeScript + ESLint(如
react/no-danger、no-eval)在开发期拦截高危模式
若真需运行时对象保护,应作用于数据层而非 props
如果业务有强一致性要求(如配置对象、状态快照),可对原始数据源做封装:
- 用
Object.freeze(比seal更严格)冻结不可变数据结构 - 通过自定义 Hook 返回代理对象(
Proxy)实现细粒度访问控制与日志 - 在 Redux / Zustand 等状态管理中,确保 reducer 和 action payload 经过验证后再合并
这些操作应在数据进入组件前完成,而不是在组件体内对 props 动手脚。











