[DataGrid] Fix crash when grouping/tree-data values match Object.prototype property names#22312
[DataGrid] Fix crash when grouping/tree-data values match Object.prototype property names#22312LukasTy wants to merge 1 commit intomui:masterfrom
Conversation
…totype property names
The row-tree builder used plain `{}` objects as hash maps keyed by
user-supplied grouping values. Looking up `'constructor'` (or
`'__proto__'`, `'toString'`, etc.) returned the inherited
`Object.prototype` property instead of `undefined`, so the code thought
a node already existed at that path and crashed when it tried to use
the prototype function as a node id.
Switch the `childrenFromPath` lookup objects to `Object.create(null)`
so user-supplied keys can never collide with `Object.prototype`. This
matches existing usage in the sorting/filter selectors.
Fixes mui#22310
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Deploy previewhttps://deploy-preview-22312--material-ui-x.netlify.app/ Bundle size
Check out the code infra dashboard for more information about this PR. |
There was a problem hiding this comment.
Pull request overview
Fixes a Data Grid crash in row-grouping and tree-data when user-provided grouping keys/path segments collide with Object.prototype property names (e.g. "constructor", "__proto__", "toString"). The fix prevents prototype pollution / prototype-chain lookups by using prototype-less objects as the internal hash maps for childrenFromPath.
Changes:
- Replace
{}maps used forchildrenFromPath(and its per-field nested maps) withObject.create(null)in row-tree construction and tree-data reorder logic. - Add regression tests covering problematic grouping values in row grouping and tree-data paths.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| packages/x-data-grid/src/hooks/features/rows/gridRowsUtils.ts | Makes the root group’s childrenFromPath prototype-less to avoid key collisions with Object.prototype. |
| packages/x-data-grid-pro/src/utils/tree/utils.ts | Ensures newly created per-field childrenFromPath[groupingField] maps are prototype-less. |
| packages/x-data-grid-pro/src/utils/tree/insertDataRowInTree.ts | Creates group nodes with prototype-less childrenFromPath during tree insertion/building. |
| packages/x-data-grid-pro/src/hooks/features/treeData/treeDataReorderExecutor.ts | Uses a prototype-less childrenFromPath when converting a leaf to a group during drop-on-leaf reorder. |
| packages/x-data-grid-pro/src/tests/treeData.DataGridPro.test.tsx | Adds regression test for tree-data paths beginning with "constructor". |
| packages/x-data-grid-premium/src/tests/rowGrouping.DataGridPremium.test.tsx | Adds regression test for row-grouping values colliding with Object.prototype property names. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
Should we also cherry-pick this v7? |
MBilalShafi
left a comment
There was a problem hiding this comment.
Should we also cherry-pick this v7?
I think so. The effort should be minimal.
Fixes #22310
Summary
The Data Grid (Pro & Premium) crashed with a white screen when a row-grouping value or tree-data path segment was equal to
'constructor'(or any otherObject.prototypeproperty name like'__proto__','toString','hasOwnProperty','valueOf').Reproduction (from the issue): https://codesandbox.io/p/devbox/mui-datagrid-nested-rows-geographic-example-forked-jnswls
Fixed example: https://stackblitz.com/edit/avpph9bc?file=src%2FDemo.tsx
Root cause
The row-tree builder used plain
{}objects as hash maps keyed by user-supplied grouping values. The lookup ininsertDataRowInTree.tsdid:When the user-provided key was
'constructor',({}).constructorreturnedObject.prototype.constructor(theObjectfunction) instead ofundefined. The code then treated that function as an existing node id, fetchedtree[Object](undefined), and crashed when trying to read.type/.isAutoGeneratedon it.Fix
Switch the
childrenFromPathlookup objects from plain{}toObject.create(null). Prototype-less objects do not exposeObject.prototypeproperties, so user-supplied keys can never collide withconstructor,__proto__,toString, etc. This matches existing usage ingridSortingSelector.ts,gridFilterSelector.ts, anduseGridColumnHeaders.tsx.The
GridChildrenFromPathLookuptype signature does not change; TypeScript treats it as an index signature regardless of the runtime prototype, and existing readers (map[key]) keep working unchanged.Files touched
packages/x-data-grid/src/hooks/features/rows/gridRowsUtils.ts(root group)packages/x-data-grid-pro/src/utils/tree/insertDataRowInTree.ts(3 group node construction sites)packages/x-data-grid-pro/src/utils/tree/utils.ts(inner per-field map ininsertNodeInTree)packages/x-data-grid-pro/src/hooks/features/treeData/treeDataReorderExecutor.ts(drop-on-leaf reorder)