Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[DataGrid] Fix eval blocked by CSP #9863

Merged
merged 7 commits into from
Aug 16, 2023
Merged

Conversation

romgrk
Copy link
Contributor

@romgrk romgrk commented Aug 1, 2023

Closes #9771

Feature-detect eval at runtime and only use it if available.

@romgrk romgrk added bug 🐛 Something doesn't work component: data grid This is the name of the generic UI component, not the React module! feature: Filtering Related to the data grid Filtering feature labels Aug 1, 2023
@romgrk
Copy link
Contributor Author

romgrk commented Aug 1, 2023

Should we add a test for this? Do we have a test setup that can handle adding a CSP header?

@mui-bot
Copy link

mui-bot commented Aug 1, 2023

Netlify deploy preview

Netlify deploy preview: https://deploy-preview-9863--material-ui-x.netlify.app/

Updated pages

No updates.

These are the results for the performance tests:

Test case Unit Min Max Median Mean σ
Filter 100k rows ms 311.4 514.4 339.3 388 84.562
Sort 100k rows ms 461.8 896.8 706.9 707.64 160.402
Select 100k rows ms 128.9 214.8 185 181.18 29.311
Deselect 100k rows ms 131 205.8 186.2 173.8 27.783

Generated by 🚫 dangerJS against 2f2351a

@cherniavskii
Copy link
Member

cherniavskii commented Aug 1, 2023

Do we have a test setup that can handle adding a CSP header?

Should we add a test for this? It should be fairly easy to add an e2e test that would inject CSP meta tag into the default HTML template on mount 👍

@romgrk
Copy link
Contributor Author

romgrk commented Aug 3, 2023

It should be fairly easy to add an e2e test that would inject CSP meta tag into the default HTML template on mount +1

The current implementation only detects eval once at startup. Should we move the check at each filter call? I don't love it but it's probably not very expensive.

@cherniavskii
Copy link
Member

The current implementation only detects eval once at startup. Should we move the check at each filter call? I don't love it but it's probably not very expensive.

Oh, right. Yes, moving the check to the filter call sounds good to me.
Another option is to enable CSP for all e2e tests 🙂

test/e2e/serve.json Outdated Show resolved Hide resolved
test/e2e/template.html Outdated Show resolved Hide resolved
@romgrk romgrk merged commit 0032290 into mui:master Aug 16, 2023
4 checks passed
@romgrk romgrk deleted the fix-filter-eval-csp branch August 16, 2023 09:34
Copy link
Member

@oliviertassinari oliviertassinari left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would using Function over eval be safer and yield similar performance?

@@ -278,25 +290,27 @@ describe('<DataGrid /> - Filter', () => {
const ALL_ROWS = ['', '', '', 'France (fr)', 'Germany', '0', '1'];

it('should filter with operator "contains"', () => {
expect(getRows({ operator: 'contains', value: 'Fra' })).to.deep.equal(['France (fr)']);
testEval(() => {
Copy link
Member

@oliviertassinari oliviertassinari Aug 16, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This means we no longer run any of the assertions below in the tests, no? It seems it's not what we intended.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AFAICT we're running them twice, eval and non-eval. testEval is synchronous. Unless I'm misunderstanding.

Copy link
Member

@oliviertassinari oliviertassinari Aug 16, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From what I understood, this would provide the intended behavior:

diff --git a/packages/grid/x-data-grid/src/tests/filtering.DataGrid.test.tsx b/packages/grid/x-data-grid/src/tests/filtering.DataGrid.test.tsx
index e5ab37fa5..2b42b9f7b 100644
--- a/packages/grid/x-data-grid/src/tests/filtering.DataGrid.test.tsx
+++ b/packages/grid/x-data-grid/src/tests/filtering.DataGrid.test.tsx
@@ -44,16 +44,14 @@ describe('<DataGrid /> - Filter', () => {
   let disableEval = false;

   function testEval(fn: Function) {
-    return () => {
-      disableEval = false;
-      fn();
-      disableEval = true;
-      fn();
-      disableEval = false;
-    };
+    fn();
+    disableEval = true;
+    fn();
+    disableEval = false;
   }

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just noticed this when adding new tests 😅
#10587

@@ -245,6 +245,12 @@ DataGridPremiumRaw.propTypes = {
* @default false
*/
disableDensitySelector: PropTypes.bool,
/**
* If `true`, `eval()` is not used for performance optimization.
* @default false
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are we sure about this opt-out? eval could be a security hole.

Copy link
Contributor Author

@romgrk romgrk Aug 16, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have reviewed the eval'd code in #9635 and #9120 and we haven't found any remaining security risk. In particular, we ensure that no user inputted string can end up in the eval'd code without being properly escaped (aka no XSS). There are only two user inputs, applier.item.id and applier.item.field. We pass them both through JSON.stringify, which by the spec returns a valid & properly escaped string representation for JS/JSON.

If we do find a security risk, then it would be best to simply not include the feature.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alright 👍

@romgrk
Copy link
Contributor Author

romgrk commented Aug 16, 2023

Would using Function over eval be safer and yield similar performance?

Not safer, it's the same fundamental mechanism, string -> code. eval is needed here to preserve the lexical context, Function creates a function in the global scope.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug 🐛 Something doesn't work component: data grid This is the name of the generic UI component, not the React module! feature: Filtering Related to the data grid Filtering feature regression A bug, but worse
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Content Security Poilicy] Filtering in x-data-grid broken after update to v6.10.1 due to eval
4 participants