Chrome extension compiled by Webpack throws `unsafe-eval` error - javascript

I get this error when reloading my Chrome Extension after compiling using Webpack:
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' blob: filesystem: chrome-extension-resource:".
at new Function (<anonymous>)
at evalExpression (compiler.js:33919)
at jitStatements (compiler.js:33937)
at JitCompiler.webpackJsonp.../../../compiler/esm5/compiler.js.JitCompiler._interpretOrJit (compiler.js:34520)
at JitCompiler.webpackJsonp.../../../compiler/esm5/compiler.js.JitCompiler._compileTemplate (compiler.js:34448)
at compiler.js:34347
at Set.forEach (<anonymous>)
at JitCompiler.webpackJsonp.../../../compiler/esm5/compiler.js.JitCompiler._compileComponents (compiler.js:34347)
at compiler.js:34217
at Object.then (compiler.js:474)
My CSP grants the unsafe-eval permission.
"content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self'"
How can I permit the use of eval() in my code (because Webpack uses this to generate source maps)?

Took me a few hours but what you probably want to do is change the style of source mapping webpack uses.
By default it uses eval.
https://webpack.js.org/configuration/devtool/
I added this to my webpack.config.js:
devtool: 'cheap-module-source-map'
The trick to this was figuring out why webpack --mode development has the error and webpack --mode production didn't.
Also I'm using React not Polymer but I'm pretty sure this still applies.

Interesting read to overcome via Manifest
https://developer.chrome.com/extensions/contentSecurityPolicy
Evaluated JavaScript
The policy against eval() and its relatives like
setTimeout(String), setInterval(String), and new Function(String) can
be relaxed by adding 'unsafe-eval' to your policy:
"content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self'"
However, we strongly recommend against doing this.
These functions are notorious XSS attack vectors.

Thanks for the answer from #Randy. However, For Vue CLI generated vue project, there's no webpack.config.js, so the solution will be adding the following config into vue.config.js:
configureWebpack: {
devtool: 'cheap-module-source-map'
}

A chrome extension is not allowed to use unsafe-eval, or eval at all in fact.
https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Content_Security_Policy
When making a Chrome extension understand that it's severely limited by Content Security Policies. Make sure you read and understand the WebExtensions Content Security Policy. If you want to have an inline script like:
<script>
alert('hello')
</script>
You're gonna have to calculate the script tags contents into its SHA256 value and add that to your manifest in order for it to be allowed to be executed.

Webpack V5
Use --no-devtool to get out of trouble quickly.
No eval code, no .map file.
npx webpack watch --no-devtool
webpack cli
https://webpack.js.org/api/cli#negated-flags

FYI, I meet this issue because I add istanbul plugin in babel.config.js.
And the build result contains new Function('return this')

For Manifest 3 you can use
"content_security_policy": {
"extension_page":"script-src 'self' 'wasm-unsafe-eval'; object-src 'self'"
}

Scripts from external domains are not allowed in mv3, all scripts must be included into extension package.
Please see the Migrating to Manifest V3.

In my case working on an MVC 5 application, all I had to do was to install the Nuget package in Visual Studio: 'NWebsec.Mvc' and the application ran just fine.

Related

How to use importmap while developing an extension for chrome

I am trying to create chrome extension that uses Three.js and some of its plugins and I cannot import them without an importmap as the modules themselves are importing Three.js as 'three' without the path to three.module.js.
However, when trying to use an importmap I run into CSP violation as it would be an inline script. Even after adding the lines bellow into my manifest.json (manifest version 3), I still get CSP violations.
"content_security_policy": {
"script-src": "'self' 'unsafe-inline' 'sha256-InlineScriptHash' 'nonce-NonceAddedToInline'"
},
How should the "content_security_policy" be changed to allow importmap or how should I go about importing Three.js plugins?

Why JS scripts of type "module" need a web server to work? [duplicate]

Alright, I have looked on this site and have found several different answers, none of which have worked for me.
Basically had a js file that had many functions in it along with the main code for the app. I wanted to move all my functions to another js file so that I could clean up my code a little. I am fairly new to js but I know in python it was as simple as saying "import (module) as (nickname) from (path)"
anyways let's say I have a function named show message in my functions.js module.
export function show_message(){
alert("Hello");
}
and then I at the top of my main.js file I did
import { show_message } from './functions.js'
//I have also tried to import like this:
import * as func from './functions.js'
//And then I call it
show_message();
//I have also tried
func.show_message();
I know this is something simple, but as I said everywhere I have looked I have seen different answers, none of which work for me. I am using Firefox btw. I am also getting an error in the console saying that my import declarations need to be at the top of my module, I fixed that by specifying the type in my HTML link (script src="/static/main.js" type="module")
The error went away but is now saying "same origin policy disallows reading the remote resource at the file (path) (reason: cors request not HTTP)."
And the other error says "module source URI is not allowed in this document".
which makes me think maybe my syntax for importing is right and the error is in my HTML code?
Any help is appreciated.
0. The short answer
You need to install and run a local web server. - For a suggestion on how,
read on.
1. The basics
I tried a simple HTML file – index.html – as follows:
<!-- index.html - minimal HTML to keep it simple -->
<html>
<head>
<meta charset="UTF-8">
<link rel="shortcut icon" href="#">
</head>
<body>
<h1>Hello world!</h1>
<p>Experimenting with JavaScript modules.</p>
<script type="module" src="js/functions.js"></script>
</body>
</html>
In the subfolder js I put the JavaScript file functions.js:
// js/functions.js
alert('Hello');
When double-clicking index.html, my default web browser – Firefox 89.0
(64-bit) – shows the following, after pressing F12.
Notice how the JavaScript code is not running:
The error message:
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at file:///C:/stackexchange/reproduce/jsModule/moduleNW/basics/js/functions.js. (Reason: CORS request not http).
A cheating "solution" is to (temporarily) remove type="module" from the HTML
code.
The alert then displays without errors.
But I want to run the JavaScript code as a module, so I put back
type="module" in the HTML.
2. Install and run a local web server
To run it as a module, it needs to run on a web server.
Thus, if you want to run the code on your own computer, you will need to
(install and) start a local web server.
One currently popular alternative is live-server.
Here is what worked for me.
Open a terminal. (On Windows: cmd.exe.)
Type npm and hit Enter to see if Node.js is installed.
If you get command not found, download at https://nodejs.org/en/download/
and install. 1
(On Ubuntu, you can try sudo apt install -y nodejs.)
Install live-server: npm install live-server -g.
Change directory to where your page lives: cd <path-to-index.html>.
Start the server: live-server .
(Should open localhost:8080 in your default browser and show the alert.
See below.)
Note 1.
I am on Windows 10, but the above instructions should work fine on Linux and
macOS too.
Note 2.
Here I used Firefox 89.0, but I have tried Google Chrome 91.0 as well.
The only notable difference is the CORS error message, which in Chrome reads:
Access to script at 'file:///C:/stackexchange/reproduce/jsModule/basics/js/functions.js' from origin 'null' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-extension, chrome-untrusted, https.
3. Exporting and importing
Next I create a new folder demo2 containing the following demo2.html:
<!-- demo2.html - even shorter HTML for simplicity -->
<body>
<h1>Hello world!</h1>
<p>Javascript modules.</p>
<script type="module" src="js/main.js"></script>
</body>
I also create the following three JavaScript files in the subfolder js:
// js/module1.js
export function hi () { console.log('Hi from module 1.'); }
and
// js/module2.js
export function howdy () { console.log('Howdy from module 2!'); }
and
// js/main.js
import { hi } from './module1.js';
import { howdy } from './module2.js';
hi();
howdy();
Now I run live-server from the terminal in the folder where demo2.html
resides.
This time I start by typing
live-server --port=1234 --entry-file=demo2.html
and hitting Enter. Screenshot:
References:
Installing Node.js live-server
The live-server docs
Live-server can't find the file specified
Export and Import
1 On Windows 10, I once needed to
repair the installation.
On the script tag you are using to load the js in the browser you need to add the attribute
type="module"
It will look like the following:
<script type="module">
import {addTextToBody} from './utils.mjs';
addTextToBody('Modules are pretty cool.');
</script>
utils.mjs:
export function addTextToBody(text) {
const div = document.createElement('div');
div.textContent = text;
document.body.appendChild(div);
}
This is if you are not using a bundler like webpack and working directly in the browser.
Source of code: https://jakearchibald.com/2017/es-modules-in-browsers/
You might want to use broswerify instead. It allows you to write NodeJS-style modules and then compiles them into a single browser-friendly JavaScript file, allowing you to get all the performance benefits of loading only a single file. It also means you can easily use the same code both server side and client side.
If you want to stick with separate files, it looks like you are well on your way. Unlike regular JavaScript files, modules are subject to Cross-Origin Resource Sharing (CORS) restrictions. They have to be loaded from the same origin, and cannot be loaded from the local filesystem. If you are loading them from the local file system, move them to a server. If you are already hosting them on a server, add the Access-Control-Allow-Origin: * header to the response that serves the module file.
Lots more gotchas and solutions here and here.
function show_message(){
alert("Hello");
}
export { show_message };
and
import { show_message } from './functions'
i think this should do the trick. this is a named export/import technique. you can under this name find more information if you desire it.
Shortcut for Accepted answer
In case you are using Visual Studio Code just install the Live Preview extension by Microsoft.
In any HTML file click the Show preview icon. It will automatically run a local server and show up in the code editor. After every edit you make it refreshes. You can also show it in your default browser.
No need for command line anymore!
JavaScript has had modules for a long time. However, they were implemented via libraries, not built into the language i.e. you can't import or export part of those modules into your js files (whole library needs to be loaded). ES6 is the first time that JavaScript has built-in modules.
Please refer Here for more info about ES modules.
But things have changed and ES modules are now available in browsers! They're in…
Safari 10.1+, Chrome 61+, Firefox 60+, Edge 16+, etc,.
Now, you need to create your JS file using a new extension .mjs, like,
// utils.mjs
export function addTextToBody(text) {
const div = document.createElement('div');
div.textContent = text;
document.body.appendChild(div);
}
and then, you can import that file into your html page like,
<script type="module">
import {addTextToBody} from './utils.mjs';
addTextToBody('Modules are pretty cool.');
</script>
Please refer Here for more info about using ES module in browsers.
Consider going through this url some extension might be causing an issue with the loading of modules:
This blog might be an answer to what you're expecting.
You should first check if browser accepts type="module" and use fallback if it doesn't like this:
<script type="module" src="module.mjs"></script>
<script nomodule src="fallback.js"></script>
This might be the main reason for the CORS error as written here:
Unlike regular scripts, module scripts (and their imports) are fetched
with CORS. This means cross-origin module scripts must return valid
CORS headers such as Access-Control-Allow-Origin: *
So you need to add CORS header to the module file
Consider this blog for CORS issue. You should add CORS header ie. Access-Control-Allow-Origin: * to the server config most probably.
Using JS modules in the browser
On the web, you can tell browsers to treat a element as a module by setting the type attribute to module.
<script type="module" src="main.mjs"></script>
<script nomodule src="fallback.js"></script>
More on
https://developers.google.com/web/fundamentals/primers/modules
If you're using webpack and babel and want to import the code into your bundle, I guess it should be one of the following:
export default function show_message(){
alert("Hello");
}
and then in your code:
import show_message from 'path/to/show_message.js'
// or
import { default as someOtherName } from 'path/to/show_message.js'
Or if you'd like to export several functions:
const show_message = function(){
alert("Hello");
}
export { show_message };
and then in your code:
import { show_message } from 'path/to/show_message.js'
// or
import { show_message as someOtherName } from 'path/to/show_message.js'
Hope that helps.
I know this old thread but I just fixed this problem myself by using Parcel to launch my website Parcel index.html, in my situation I was using Live server and it didn't work until I switched to parcel .
Instead of using .js, try using .mjs.
Let's say your module file is /modules/App.js, just change it to /modules/App.mjs.
And ofcourse, make sure you have added type="module" in script tag, like this - <script type="module" src="./index.js" defer></script>
My folder structure -
index.html
index.js
modules/App.mjs
This worked for me!

Self-hosted phaser 3 library: this is undefined?

I am absolutely new with phaser 3.
I have installed the library with npm. Then I naively fetch the bundled file from node_modules.
<body>
<script src="./node_modules/phaser/dist/phaser-arcade-physics.js"></script>
<script src="./js/start.js"></script>
</body>
When I load index.html in the browser as file, it works fine. But now I have created a little v-host in my Apache and let it serve the files. This works too, but phaser yells at me:
Uncaught TypeError: this.texture is undefined
setFrame http://game.localhost/personwar/node_modules/phaser/dist/phaser-arcade-physics.js:138726
setTexture http://game.localhost/personwar/node_modules/phaser/dist/phaser-arcade-physics.js:138699
Image http://game.localhost/personwar/node_modules/phaser/dist/phaser-arcade-physics.js:29328
<anonymous> http://game.localhost/personwar/node_modules/phaser/dist/phaser-arcade-physics.js:168386
create http://game.localhost/personwar/js/start.js:34
[...]
DOMContentLoaded http://game.localhost/personwar/node_modules/phaser/dist/phaser-arcade-physics.js:86811
Game http://game.localhost/personwar/node_modules/phaser/dist/phaser-arcade-physics.js:154945
<anonymous> http://game.localhost/personwar/js/start.js:17
I have stolen start.js from the beginner tutorial and here it all starts:
function create () {
console.log('this', this);
this.add.image(0, 0, 'bg').setOrigin(0, 0);
...
}
I don't understand, why this.texture changes when the library is self hosted, compared to being delivered by file://. What do I need to change here?
It might be a timing problem, maybe I need to setup smth else before calling this.add.image in the create callback.
I will go on with investigating, what texture actually is.
Issue were Header, which was set by server: Content-Security-Policy
The rule "default-src 'self'; style-src 'self' 'unsafe-inline'; object-src 'none'"
blocked this call
blob:http://game.localhost/b6ac3ad7-e25b-4b82-8d07-8f4ce6c331c3
which was the call for one of our images. This is weird and I don't get it. But the point is: no image loaded -> no texture.
Well I don't know which file your are linking. the main phaser file is called phaser.js or phaser.min.js. I think this is the root of your problem.
The easy solution is to download the phaser javascript file into your webfolder, or link it from a cdn. (https://phaser.io/download/stable)
If you (want to) use npm you will need a bundler like webpack, parcel, ... there are serval templates out there. (like this one https://github.com/photonstorm/phaser3-project-template).
btw.: I'm no expert, but I would in general never have the node_modules directory in a webserver accessible folder (if not really needed, and if you are running apache, it is probably not needed), since this could create be a potential security risk.

How can I use "import something from package" in script starting from electron-quick-start

I am new to electron. So far I can run electron-quick-start but I get stuck when try using
import {somthing} from "package"
Here is what I did from electron-quick-start.
Edit ./renderer.js as
import { TitleBar } from "electron-react-titlebar";
import "electron-react-titlebar/assets/style.css";
ReactDOM.render(<TitleBar />, document.querySelector("title-bar"));
index.html:
...
<head>
<meta http-equiv="Content-Security-Policy" content="script-src https://www.google-analytics.com 'self' file://* 'unsafe-inline' 'unsafe-eval'">
</head>
<body>
<title-bar></title-bar>
...
main.js (seems I need to change loadFile to loadURL)
...
mainWindow.loadURL(`File://${__dirname}/index.html`);
// Open the DevTools.
mainWindow.webContents.openDevTools();
...
After this I get an error
renderer.js:7 Uncaught SyntaxError: Cannot use import statement outside a module
I did some research by setting
"type": "module"
in package.json, and this gets errors about module/commonjs.
I then find other projects when importing modules they write requires in
<script>require("./renderer")</script>
but I got
index.html:17 Uncaught ReferenceError: require is not defined
Then I tried babel / browserify and many other things only to find my simple test project messed up.
I googled for ES6-react-electron sample minimal projects but they are too out-dated that I find many deprecated packages. These projects still get errors
So, can someone make a modernized minimal example which starts from electron-quick-start and
1. use "import" in script
2. (optional) somehow use "require" to import other modules in index.html
I believe the example should be quite simple but I just missed some points.
Best if somebody can just post a GitHub repo that everybody else can starts happy coding from just pulling it! Thanks!

Content Security Policy error with Vue JS, Webpack and JSP

I am trying to integrate Vue JS in one of my application with latest version 2.4.2.Backend implementation uses struts and we set Content-Security-Policy script-src 'self' 'unsafe-inline' in response headers.
At first I was trying to use standalone Vue JS instead of using webpack or any other tool. I see the following CSP error when I execute my page using Vue JS :
[Vue warn]: It seems you are using the standalone build of Vue.js in an environment with Content Security Policy that prohibits unsafe-eval. The template compiler cannot work in this environment. Consider relaxing the policy to allow unsafe-eval or pre-compiling your templates into render functions.
warn — vue.min.js:485
compileToFunctions — vue.min.js:9842
$mount — vue.min.js:10040
Global Code — example.do:51
To avoid this issue, I have started using webpack to pre-compile the templates so that the issue will be resolved and I still see the below error in webpack JS :
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' 'unsafe-inline'".
Is there any solution to use webpack / Vue JS with CSP's enabled ? What is the suitable solution to handle CSP issues.
Sample Example : Vue is not detected when JSP is loaded through struts
Thanks for your help in advance.
Got to know there are different options to set up "devtools" attribute in webpack config file.
Issue and solution details : https://github.com/webpack/webpack/issues/4094
https://webpack.js.org/configuration/devtool/#devtool explains detailed options and selection to resolve CSP issues.

Categories