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

Uncaught EvalError: 'unsafe-eval' is not an allowed source of script in the following Content #713

Open
charutiwari04 opened this issue Dec 19, 2018 · 26 comments · May be fixed by #2672
Open

Comments

@charutiwari04
Copy link

Hi, I am getting following error from excel.min.js for using new Function(). I am not able to use exceljs. Please help


exceljs.min.js:9 Uncaught EvalError: Refused to evaluate a string as JavaScript because 'unsafe-eval' is not an allowed source of script in the following Content Security Policy directive: "script-src 'self':

at new Function (<anonymous>)
at b (exceljs.min.js:9)
at exceljs.min.js:9
at Object.118 (exceljs.min.js:9)
at e (exceljs.min.js:3)
at exceljs.min.js:3
at Object.119../declare.js (exceljs.min.js:10)
at e (exceljs.min.js:3)
at exceljs.min.js:3
at Object.<anonymous> (exceljs.min.js:10)
@Siemienik
Copy link
Member

hello @charutiwari04, did You fix it? Could you write some additional info?

@charutiwari04
Copy link
Author

Hi @Siemienik, I am not able to solve it. This is what i have. the above error is content security policy error.

@Siemienik
Copy link
Member

Siemienik commented Jan 14, 2019

@charutiwari04 have you any example code/repo/gist?

@charutiwari04
Copy link
Author

@Siemienik Here it is. Below function is being called when button is clicked.

import * as Excel from 'exceljs';
exportExcel(){
    var workbook = new Excel.Workbook();
    var worksheet = workbook.addWorksheet('Log');
    worksheet.columns = [
      { header: "IP Number", key: 'ip_address', width: 10 },
      { header: "Actor", key: 'actor_type', width: 10 },
      { header: "Date/Time (PST/PDT)", key: 'date_created', width: 20 },
      { header: "ID", key: 'activity_id', width: 15, numFmt: '0' },
      { header: "Action", key: 'action_type', width: 10 },
      { header: "Action Data", key: 'action_data', width: 30, numFmt: '@' }
    ];
    worksheet.addRows(this.props.data);
    workbook.xlsx.writeFile('act1.xlsx').then(function() {
      console.log("saved");
    });
  }

@Siemienik
Copy link
Member

Siemienik commented Jan 14, 2019

@charutiwari04 I've just tested your example, and I note, that the wrong data type pushed into addRows cause thrown errors.

this.props.data should be an array. is it?

@papandreou
Copy link
Contributor

papandreou commented Jan 15, 2019

Does it work if you add script-src 'self' 'unsafe-eval' to the Content-Security-Policy of the web page (or Chrome Extension or whatever) that you're trying to use exceljs on, as the error message suggests?

It looks like the "dist" version of the lib does contain new Function, which would explain why that directive is needed.

@charutiwari04
Copy link
Author

charutiwari04 commented Jan 15, 2019

@papandreou Perfect Solution. It is working for me. Thank You. After I added script-src: 'self' 'unsafe-eval'.This is the working modified code:

var workbook = new Excel.Workbook();
    var worksheet = workbook.addWorksheet('Log');
    worksheet.columns = [
      { header: "IP Number", key: 'ip_address', width: 10 },
      { header: "Actor", key: 'actor_type', width: 10 },
      { header: "Date/Time (PST/PDT)", key: 'date_created', width: 20 },
      { header: "ID", key: 'activity_id', width: 15, numFmt: '0' },
      { header: "Action", key: 'action_type', width: 10 },
      { header: "Action Data", key: 'action_data', width: 30, numFmt: '@' }
    ];
    var firstRow = worksheet.getRow(1);
    firstRow.font = { name: 'New Times Roman', family: 4, size: 10, bold: true, color: {argb:'80EF1C1C'} };
    firstRow.alignment = { vertical: 'middle', horizontal: 'center'};
    firstRow.height = 20;
    worksheet.addRows(data);
    var buff = workbook.xlsx.writeBuffer().then(function (data) {
     var blob = new Blob([data], {type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"});
      const url = window.URL.createObjectURL(blob);
     const anchor = document.createElement('a');
     anchor.href = url;
     anchor.setAttribute('download', 'Log.xls');
     document.body.appendChild(anchor)
     anchor.click();

@Siemienik Siemienik added the bug label Jan 15, 2019
@pierre-aurele-martin
Copy link

Following this bug that I had too

The new Function() which make CSP unsafe-eval not happy is in declare.js - not updated since a long time

declare.js is required by extended.js required by fast-csv required by exceljs (something like that)

Allow 'unsafe-eval' in CSP is not a solution we could afford as it reduces the CSP purpose ! The only solution I've found so far is to :

  • tell webpack to resolve declare.js through a custom path ;
  • the custom path being a fork of declare.js in which I replace new Function() by function(){}

I'll submit a PR to declare.js in order to fix that. But, if it's never accepted, what do you think will be the best solution for exceljs ?

One solution is to define an option to toggle the load of CSV capabilities (and therefor fast-csv) but not super practical as it means you can not use work on CSV with strong CSP.

@zachariahtimothy
Copy link

@pierre-aurele-martin did you ever submit a PR for this issue? I am like you and cannot allow unsafe-eval.

@cashewnuts
Copy link

The unsafe-eval problem has been existing so long.
I finally manage to find the cause.

The cause is that regenerator library (regenerator-runtime) requires us to not be running on strict mode.
See this comment.
https://github.com/facebook/regenerator/blob/491714f6aac228397bd845a83faf18dda966e366/packages/regenerator-runtime/runtime.js#L719-L728

As a quick fix, I modified dist/exceljs.js with this command and check if it works. This worked great on CSP protected page!

sed -i "s/[\"|']use strict[\"|']/;/g" dist/exceljs.js

I also confirmed tests pass.

npm run build && sed -i "s/[\"|']use strict[\"|']/;/g" dist/exceljs*js && npm run test:jasmine

Unfortunately I don't know much about grunt and browserify. So I can't immediately make a pull-request according to this.

@dominic-simplan
Copy link

dominic-simplan commented Jul 15, 2020

So it seems like fast-csv was actually an issue but has been fixed in the meanwhile and this should not cause errors anymore.
However, the unsafe-eval Error is still thrown, so there must be some other reason.

@cashewnuts Are you sure that the regenerator library was the cause? It seems to be only a devDependency, so why would it cause an error at runtime? Or is it used by one of the dependencies?

Edit: Okay it seems the regenerator-runtime is required here: https://cdn.jsdelivr.net/npm/exceljs@4.1.1/dist/es5/exceljs.browser.js
Where is the "use strict" at top of this script coming from?

@mdantonio
Copy link

regenerator-runtime reports (here) the following comment:

try {
  regeneratorRuntime = runtime;
} catch (accidentalStrictMode) {
  // This module should not be running in strict mode, so the above
  // assignment should always work unless something is misconfigured. Just
  // in case runtime.js accidentally runs in strict mode, we can escape
  // strict mode using a global Function call. This could conceivably fail
  // if a Content Security Policy forbids using Function, but in that case
  // the proper solution is to fix the accidental strict mode problem. If
  // you've misconfigured your bundler to force strict mode and applied a
  // CSP to forbid Function, and you're not willing to fix either of those
  // problems, please detail your unique predicament in a GitHub issue.
  Function("r", "regeneratorRuntime = r")(runtime);
}

This comment definitely confirms (if still needed) that the strict mode is the problem... Is there any chance to officially solve this issue?
The trick suggested by @cashewnuts (really thank you for that) is very tempting, but it is quite dirty

@charleaux
Copy link

Is there any way we can get this bumped in priority?

@laurisvan
Copy link

Since my project very much needs CSP to work and we are using this package, I spent some time investigating this one.

It appears "use strict" is may be added by browserify process already, and it seems like the interplay with babel just makes it more difficult. There are many ways to disable babel from adding "use strict" definitions, but as they are not defined by babel at all, all the known ways seem to fail (I tried many).

I haven't been played with ES transpilation lately, but I must ask if we even need Browserify anymore? Could the stack be simplified by using babel alone, and the "use strict" definitions would be easier to solve?

@laurisvan
Copy link

I made a PR #1664 for a brute force replacement of "use strict". I believe it should have no shortcomings except that somebody could slip unstrict code into web builds. I believe most of us use ExcelJS bundled with Webpack or such, so I believe the builds are already strict by various other ways.

Please let me know if this works for you and whether it is an acceptable fix to the problem.

@notclive
Copy link

I've worked around this issue on my project by importing the bare version of exceljs, which doesn't include any polyfills (including regenerator-runtime), and importing regenerator-runtime separately.

@laurisvan
Copy link

@notclive How did you manage to do such an import? Would be nice to get it working in our webpack based build.

@notclive
Copy link

notclive commented Jul 5, 2021

@notclive How did you manage to do such an import? Would be nice to get it working in our webpack based build.

We put the following in our webpack config

resolve: {
        alias: {
            'exceljs': 'exceljs/dist/exceljs.bare.min.js'
        }
    }

@FantomNY
Copy link

FantomNY commented Nov 17, 2021

Following this bug that I had too

The new Function() which make CSP unsafe-eval not happy is in declare.js - not updated since a long time

declare.js is required by extended.js required by fast-csv required by exceljs (something like that)

Allow 'unsafe-eval' in CSP is not a solution we could afford as it reduces the CSP purpose ! The only solution I've found so far is to :

  • tell webpack to resolve declare.js through a custom path ;
  • the custom path being a fork of declare.js in which I replace new Function() by function(){}

I'll submit a PR to declare.js in order to fix that. But, if it's never accepted, what do you think will be the best solution for exceljs ?

One solution is to define an option to toggle the load of CSV capabilities (and therefor fast-csv) but not super practical as it means you can not use work on CSV with strong CSP.

Thank you very much. I spend 4 hours finding a decision. Its really works. I just replace by step 2 the original file (exceljs.min.js). Greet day.

@achimmihca
Copy link

achimmihca commented Aug 23, 2022

Duplicate of #512

I still find Function('return this') in current versions of this lib, when looking in node_modules/exceljs/dist/exceljs.bare.min.js.
Has no fix arrived yet in exceljs?

@watton-chen
Copy link

The unsafe-eval problem has been existing so long. I finally manage to find the cause.

The cause is that regenerator library (regenerator-runtime) requires us to not be running on strict mode. See this comment. https://github.com/facebook/regenerator/blob/491714f6aac228397bd845a83faf18dda966e366/packages/regenerator-runtime/runtime.js#L719-L728

As a quick fix, I modified dist/exceljs.js with this command and check if it works. This worked great on CSP protected page!

sed -i "s/[\"|']use strict[\"|']/;/g" dist/exceljs.js

I also confirmed tests pass.

npm run build && sed -i "s/[\"|']use strict[\"|']/;/g" dist/exceljs*js && npm run test:jasmine

Unfortunately I don't know much about grunt and browserify. So I can't immediately make a pull-request according to this.

manifest v3, it worked, thank you!

@ftes
Copy link

ftes commented Feb 13, 2023

The easiest workaround for us:
import exceljs/dist/exceljs.bare.min.js

Our build takes care of polyfills by itself anyway.

Thanks @notclive.

@dmathisen
Copy link

dmathisen commented Jun 7, 2023

I managed to fix this by simply importing regenerator-runtime before importing exceljs. I don't know why it works (I figure it's importing a later, patched version) and I don't know if it's a good or bad idea, but it did work.

import 'regenerator-runtime';
import { Table, Workbook, Worksheet } from 'exceljs';

And as others have mentioned, adding script-src 'self' 'unsafe-eval' is NOT a fix.

Edit: maybe it's safer to first add regenerator-runtime as a separate package (npm -i regenerator-runtime)?

@mahanandyadav
Copy link

I've worked around this issue on my project by importing the bare version of exceljs, which doesn't include any polyfills (including regenerator-runtime), and importing regenerator-runtime separately.

this worked for me:
import 'regenerator-runtime/runtime'; // Import regenerator-runtime separately
import ExcelJS from 'exceljs/dist/exceljs.min'; // Import the bare version of exceljs

@cherniavskii
Copy link

Hi,
I'm coming from this issue in MUI X: mui/mui-x#11153
I've inspected the exclejs build from NPM and the new Function() seems to be coming from the jszip dependency:

https://github.com/Stuk/jszip/blob/2ceb998e29d4171b4f3f2ecab1a2195c696543c0/dist/jszip.js#L11404


The new Function in jszip is coming from browserify's insert-module-globals.

@cherniavskii
Copy link

Since jszip is not maintained anymore (the last release was in August 2022), would it make sense to migrate to https://github.com/101arrowz/fflate?
This would fix this CSP issue, but also reduce the bundle size a bit (~16kB gzipped).

@Siemienik What do you think? I can give it a try, but I would appreciate some guidance if there's an interest in this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.