How to use importmap while developing an extension for chrome - javascript

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?

Related

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.

Has anyone seen VS Code drop file extensions when selecting a filename from the dropdown list [duplicate]

I installed chrome beta - Version 60.0.3112.24 (Official Build) beta (64-bit)
In chrome://flags/ I enabled 'Experimental Web Platform features' (see https://jakearchibald.com/2017/es-modules-in-browsers)
I then tried:
<script type="module" src='bla/src/index.js'></script>
where index.js has a line like:
export { default as drawImage } from './drawImage';
This refer to an existing file drawImage.js
what I get in the console is error in
GET http://localhost/bla/src/drawImage
If I change the export and add ".js" extension it works fine.
Is this a chrome bug or does ES6 demands the extension in this case ?
Also webpack builds it fine without the extension !
No, modules don't care about extensions. It just needs to be a name that resolves to a source file.
In your case, http://localhost/bla/src/drawImage is not a file while http://localhost/bla/src/drawImage.js is, so that's where there error comes from. You can either add the .js in all your import statements, or configure your server to ignore the extension, for example. Webpack does the same. A browser doesn't, because it's not allowed to rewrite urls arbitrarily.
The extension is part of the filename. You have to put it in.
As proof of this, please try the following:
rename file to drawImage.test
edit index.js to contain './drawImage.test'
Reload, and you'll see the extension js or test will be completely arbitrary, as long as you specify it in the export.
Obviously, after the test revert to the correct/better js extension.
ES6 import/export need “.js” extension.
There are clear instructions in node document:
Relative specifiers like './startup.js' or '../config.mjs'. They refer to a path relative to the location of the importing file. The file extension is always necessary for these.
This behavior matches how import behaves in browser environments, assuming a typically configured server.
https://nodejs.org/api/esm.html#esm_import_expressions

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

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.

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.

Does ES6 import/export need ".js" extension?

I installed chrome beta - Version 60.0.3112.24 (Official Build) beta (64-bit)
In chrome://flags/ I enabled 'Experimental Web Platform features' (see https://jakearchibald.com/2017/es-modules-in-browsers)
I then tried:
<script type="module" src='bla/src/index.js'></script>
where index.js has a line like:
export { default as drawImage } from './drawImage';
This refer to an existing file drawImage.js
what I get in the console is error in
GET http://localhost/bla/src/drawImage
If I change the export and add ".js" extension it works fine.
Is this a chrome bug or does ES6 demands the extension in this case ?
Also webpack builds it fine without the extension !
No, modules don't care about extensions. It just needs to be a name that resolves to a source file.
In your case, http://localhost/bla/src/drawImage is not a file while http://localhost/bla/src/drawImage.js is, so that's where there error comes from. You can either add the .js in all your import statements, or configure your server to ignore the extension, for example. Webpack does the same. A browser doesn't, because it's not allowed to rewrite urls arbitrarily.
The extension is part of the filename. You have to put it in.
As proof of this, please try the following:
rename file to drawImage.test
edit index.js to contain './drawImage.test'
Reload, and you'll see the extension js or test will be completely arbitrary, as long as you specify it in the export.
Obviously, after the test revert to the correct/better js extension.
ES6 import/export need “.js” extension.
There are clear instructions in node document:
Relative specifiers like './startup.js' or '../config.mjs'. They refer to a path relative to the location of the importing file. The file extension is always necessary for these.
This behavior matches how import behaves in browser environments, assuming a typically configured server.
https://nodejs.org/api/esm.html#esm_import_expressions

Categories