I added a Content-Security-Policy but still the security warning appears - electron

I added a Content-Security-Policy as suggested here: https://www.electronjs.org/docs/tutorial/security#6-define-a-content-security-policy and here: https://content-security-policy.com/examples/electron/
<html lang="en">
<head>
<meta http-equiv="Content-Security-Policy" content="default-src 'self'">
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>New Electron App</title>
</head>
<body>
<span>Our new Electron app</span>
<div id="root"></div>
</body>
</html>
But still I get this message:
“Electron Security Warning (Insecure Content-Security-Policy). This renderer process has either no Content Security Policy set or a policy with “unsafe-eval” enabled. This exposes users of this app to unnecessary security risks. This warning will not show up once the app is packaged.”
How to solve this security warning?

This is intended behaviour, as it says it will trigger on unset or set policy allowing unsafe-evals. They simply want you to make sure to not add any evals without being 100% sure.
For why this is only displayed when building it's only the case if you build your application and your binary is still called "electron".

Add script-src 'self' to the CSP:
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self';">
It should fix the issue. It's a feature of Electron security parser - it does not know abt fallback so thinks that script-src is absent, nitty-gritty is here

You can simply add this environment variable to your package.json.
{
"scripts": {
"electron": "ELECTRON_DISABLE_SECURITY_WARNINGS=true electron ."
}
}

Least two ways to disable CSP : no package.json
Disable through CLI
Consider running Electron's app source file main.js within CLI as so: ELECTRON_DISABLE_SECURITY_WARNINGS=true npx electron main.js
Hereby using npx I did consider you was clever and installed Electron locally beforehand .
Disable through the process
Define anywhere (top-level would be at best) the following process.env['ELECTRON_DISABLE_SECURITY_WARNINGS']=true
info taken from

After a lot of days searching for the solution I found at VScode sources a function when app is ready
w.protocol.registerHttpProtocol(I.Schemas.vscodeRemoteResource, (Pe, Le) => {
Le({ url: Pe.url.replace(/^vscode-remote-resource:/, 'http:'), method: Pe.method })
})
So you need a Protocol to replace to http and you have to register as privileged for example
protocol.registerSchemesAsPrivileged([{ scheme: 'server', privileges: { bypassCSP: true } }])
/*----*/
app.whenReady().then(() => {
protocol.registerHttpProtocol('server', (request, response: any) => {
const redirect: any = {
method: request.method,
url: request.url.replace(/^remote:/, 'http:')
}
if (request.method === 'POST' || request.method === 'PUT') {
redirect.uploadData = {
contentType: 'application/json',
data: request.uploadData ? request.uploadData[0].bytes.toString() : ''
}
}
response(redirect)
})
})
And then, when you make a resquest server://localhost:3000/api you don't will get the error CSP - Content-Security-Policy

Related

Electron: Google Fonts violates Content Security Policy

I'm getting a bunch of Content Security Policy errors in Electron developer console for adding google font :
Refused to load the stylesheet 'https://fonts.googleapis.com/css2?family=Inter:wght#300;400&display=swap' because it violates the following Content Security Policy directive: "default-src 'self' 'unsafe-inline' data:". Note that 'style-src-elem' was not explicitly set, so 'default-src' is used as a fallback.
I'm using electron-forge's React with TypeScript boilerplate.
Easiest way would probably be to set a Content-Security-Policy meta tag in the header of your template like this:
<head>
<meta charset="UTF-8">
<!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP -->
<meta
http-equiv="Content-Security-Policy"
content="default-src 'self';
script-src 'self';
font-src 'self' https://fonts.gstatic.com;
style-src 'self' https://fonts.googleapis.com">
<!-- ...other stuff... -->
</head>
Guide on how to use these is here:
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy#multiple_content_security_policies
I'm currently in my first hours of electron myself, without react for now, and that's how I got around it and I think that's how you're supposed to do it.

How to use html templates in electron framework?

I need to build a cross platform app with multiple windows. So I would like to know how to use html templates in electron.
Based on a similar question and what I've seen, there's no built in html template language in Electron, which is actually great because it allows you to use any other template language.
I'm currently playing with ejs in Electron.
Below is my index.ejs template file:
<html lang="en">
<head>
<title>The Index Page</title>
</head>
<body>
<h1>Welcome, this is the Index page.</h1>
<% if (user) { %>
<h3>Hello there <%= user.name %></h3>
<% } %>
</body>
</html>
And below is a section of my main.js file where the above template is rendered and loaded onto the BrowserWindow. Note that I've left out most of the boilerplate code:
const ejs = require('ejs');
//... Other code
let win = new BrowserWindow({width: 800, height: 600});
//... Other code
// send the data and options to the ejs template
let data = {user: {name: "Jeff"}};
let options = {root: __dirname};
ejs.renderFile('index.ejs', data, options, function (err, str) {
if (err) {
console.log(err);
}
// Load the rendered HTML to the BrowserWindow.
win.loadURL('data:text/html;charset=utf-8,' + encodeURI(str));
});
I'll give some credit to this gist for helping me find the data:text/html;charset=utf-8 part of the url that can be used to load dynamic content.
UPDATE
I'm actually not using this anymore. It's faster to just load the default html and use the native DOM methods. The Electron Quickstart program shows how to do this nicely.
Another option is to do the templating during your build. Here is a simple example using gulp to add nonces to the CSP meta tag and the inline script.
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'nonce-<%= scriptNonce %>';">
<title>Basic Electron App</title>
</head>
<body>
<div id="app"></div>
<script type="application/javascript" nonce=<%= scriptNonce %>>
require('./index.js');
</script>
</body>
</html>
and in gulfile.js add the following to what you already have and make sure this task is included in your pipeline. You can also just update your current html task with the code below.
const template = require('gulp-template');
const uuidv4 = require('uuid/v4');
gulp.task('copy-html', () => {
// Create nonces during the build and pass them to the template for use with inline scripts and styles
const nonceData = {
scriptNonce: new Buffer(uuidv4()).toString('base64'),
styleNonce: new Buffer(uuidv4()).toString('base64')
};
return gulp.src('src/*.html')
.pipe(template(nonceData))
.pipe(gulp.dest('dist/'));
});
This is a very stripped down example. I have a more complete example at https://github.com/NFabrizio/data-entry-electron-app if anyone is interested, though there is still one warning when running the application because one of the packages I am using pulls in react-beautiful-dnd, which adds inline styles but does not currently accept nonces.

Why do none of my plugins work for Apache Cordova?

I am using cordova to load plugins into my app. Here is the simplified reproduceable issue:
cordova create foo
cordova plugin add pluginname --save
cordova platform add android --save
cordova build android --verbose
I can run this app using phonegap and see it on my phone. The app reports deviceready as the basic starter app is supposed to. All looks great so far.
If I look in the plugin folder I can see my plugin there. In this case my plugin is called bluetoothle.
I edit the index.js file at a location that fires after the deviceready occurs and add "alert ( typeof (bluetoothle));"
I expect that when the alert fires it should report "object". It does not do this. It reports "undefined".
I have tried this with several other plugins and I always get the same result. So it would seem that no matter what plugin I install I cannot access any of the functions within the plugin.
I do have the same Problem. But I'm using the Phonegap CLI. And the following plugin: https://github.com/randdusing/cordova-plugin-bluetoothle
I add the plugin using the command:
$ phonegap plugin add cordova-plugin-bluetoothle
I've added platform android and ios.
So in the plugins folder there is the cordova-plugin-bluetoothle folder most probably being a valid plugin packet.
Also in the plugins folder there is the android.json and ios.json file containing the section:
"cordova-plugin-bluetoothle": {
"PACKAGE_NAME": "com.phonegap.helloworld"
},
in plaforms/android there is the android.json file containing:
{
"xml": "<feature name=\"BluetoothLePlugin\"><param name=\"android-package\" value=\"com.randdusing.bluetoothle.BluetoothLePlugin\" /></feature>",
"count": 1
},
in platforms/ios there is the ios.json file containing:
{
"xml": "<feature name=\"BluetoothLePlugin\"><param name=\"ios-package\" value=\"BluetoothLePlugin\" /></feature>",
"count": 1
},
I've targeted Android SDK API 23. As the readme tells...
As I have just modified the hello-world example to call bluetoothle initialize on after the deviceready event has fired.
So where could the problem be so that the bluetoothle variable is not defined in the index.js code, when the device is ready?
So here the complete code of index.js:
var bluetoothle;
var app = {
// Application Constructor
initialize: function() {
this.bindEvents();
},
// Bind Event Listeners
//
// Bind any events that are required on startup. Common events are:
// 'load', 'deviceready', 'offline', and 'online'.
bindEvents: function() {
document.addEventListener('deviceready', this.onDeviceReady, false);
},
// deviceready Event Handler
//
// The scope of 'this' is the event. In order to call the 'receivedEvent'
// function, we must explicitly call 'app.receivedEvent(...);'
onDeviceReady: function() {
app.receivedEvent('deviceready');
console.log("platform: " + device.platform);
if(bluetoothle) {
console.log("bluetooth is not defined!");
} else {
console.log("bluetooth is not defined!");
}
console.log("yhea managed to initialize Bluetooth LE!");
},
// Update DOM on a Received Event
receivedEvent: function(id) {
var parentElement = document.getElementById(id);
var listeningElement = parentElement.querySelector('.listening');
var receivedElement = parentElement.querySelector('.received');
listeningElement.setAttribute('style', 'display:none;');
receivedElement.setAttribute('style', 'display:block;');
console.log('Received Event: ' + id);
}
};
And the complete code of index.html:
<html>
<head>
<meta charset="utf-8" />
<meta name="format-detection" content="telephone=no" />
<meta name="msapplication-tap-highlight" content="no" />
<meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width" />
<!-- This is a wide open CSP declaration. To lock this down for production, see below. -->
<meta http-equiv="Content-Security-Policy" content="default-src * 'unsafe-inline'; style-src 'self' 'unsafe-inline'; media-src *" />
<!-- Good default declaration:
* gap: is required only on iOS (when using UIWebView) and is needed for JS->native communication
* https://ssl.gstatic.com is required only on Android and is needed for TalkBack to function properly
* Disables use of eval() and inline scripts in order to mitigate risk of XSS vulnerabilities. To change this:
* Enable inline JS: add 'unsafe-inline' to default-src
* Enable eval(): add 'unsafe-eval' to default-src
* Create your own at http://cspisawesome.com
-->
<!-- <meta http-equiv="Content-Security-Policy" content="default-src 'self' data: gap: 'unsafe-inline' https://ssl.gstatic.com; style-src 'self' 'unsafe-inline'; media-src *" /> -->
<link rel="stylesheet" type="text/css" href="css/index.css" />
<title>Hello World</title>
</head>
<body>
<div class="app">
<h1>PhoneGap</h1>
<div id="deviceready" class="blink">
<p class="event listening">Connecting to Device</p>
<p class="event received">Device is Ready</p>
</div>
</div>
<script type="text/javascript" src="cordova.js"></script>
<script type="text/javascript" src="js/index.js"></script>
<script type="text/javascript">
app.initialize();
</script>
</body>
</html>
Sooo,
The Issue I had before I just "worked around" by using a different Plugin for my Bluetooth Low Energy stuff.
Later I ran into the same Problem again with another Plugin.
And then I finally got the picture where it all makes sense:
I was mainly using the Phonegap Developer App to test on-the-fly.
The Phonegap Developer App comes bundled with all the Core Plugins and some others.
!! Those plugins which are not bundled already, will never be accessible for your Phonegap Developer App for testing !!
phonegap plugin add cordova-plugin-new-unbundled
Will not make it available to the App. Only download and prebuild the files for a potential real build.
To make this work in the Phonegap Developer App you would need to build your own Phonegap Developer App adding the Plugins you need.
Otherwise your Plugins are only available in a real build.

Polymer, Dart, Chrome App, CSP and debugging

Similar questions have been around for a while, maybe someone knows the answer for today's stack. Ideally preserving debuggability...
I have a Dart app which implements the GUI in Polymer/Dart and the back end in Chrome/Dart. Both parts work well (many thanks) now I am trying to tie them together and debug any problems. The unified app hits a wave of CSP errors so I have put together a tiny test case. There's a spread of Dart/Polymer/CSP advice on the net but it changes as things evolve and it's very difficult to see the current best practice. Here is the test case:
manifest.json
{
"manifest_version": 2,
"name": "Test Case",
"version": "0.3",
"icons": {"128": "dart_icon.png"},
"content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self'",
"app": {
"background": {
"scripts": ["background.js"]
}
},
"permissions": [ "usb"
, { "usbDevices": [ {"vendorId": 1027, "productId": 24597} ] }
, { "fileSystem": [ "write", "retainEntries", "directory" ] }
]
}
background.js
chrome.app.runtime.onLaunched.addListener(function(launchData) {
chrome.app.window.create('testwrap.html', {
'id': '_myMainWindow',
'bounds': {'width': 800, 'height': 500 }
});
});
testwrap.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>PolyChrome</title>
<link rel="import" href="packages/polymer/polymer.html">
<link rel="import" href="clickcounter.html">
</head>
<body>
<h1>Testing...</h1>
<p>in the test directory...</p>
<div id='container_id'>
<p id='text_id'>The log is here.</p>
</div>
<div id='div2'>
<click-counter></click-counter>
</div>
<script type='application/dart' src='testwrap.dart'></script>
</body>
</html>
testwrap.dart
import 'dart:html';
import 'package:polymer/polymer.dart';
export 'package:polymer/init.dart';
//----------------------------------------
#whenPolymerReady
void mainStartup() {
querySelector("#text_id").text = 'Running';
}
The click-counter element is the standard code from the Dart/Polymer page.
The yaml includes a $dart2js that maybe isn't used (?) or maybe having two csp:true lines is incorrect?
pubspec.yaml
name: polyChrome
description: Chrome App with Polymer
dependencies:
chrome: ^0.7.0-dev1
code_transformers: any
core_elements: any
paper_elements: any
polymer: any
transformers:
- polymer:
entry_points:
- web/testwrap.html
csp: 'true'
- $dart2js:
csp: 'true'
checked: 'true'
The CSP error messages (all the same):
Refused to execute inline script because it violates the following Content Security Policy
directive: "default-src 'self' chrome-extension-resource:".
Either the 'unsafe-inline' keyword, a hash ('sha256-...'), or a nonce ('nonce-...')
is required to enable inline execution. Note also that 'script-src'
was not explicitly set, so 'default-src' is used as a fallback.
Confusingly the test app seems to work OK despite the error messages, but a larger test freezes while booting - can't ignore the messages.
The larger test gives an error message from
Zone zone = await initPolymer();
The message is the somewhat opaque (my_clock is a test polymer component that works 100% as a web app):
Breaking on exception: Unsupported operation: Unsupported uri scheme chrome-extension for library LibraryMirror on 'my_clock'.
This isn't even a partial answer, but it may be helpful to others...
The csp lines have a common typo. Don't write:
csp: 'true'
This is correct (the same fix applies to checked: true) :
csp: true
And remove this line from the manifest:
"content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self'",
The search continues :)
here is a basic example with polymer dart
https://github.com/dart-gde/dart-chrome-app-samples/tree/master/chrome-app-with-polymer-dart
EDIT: you need in your pubspec.yaml to have these
transformers:
- polymer:
entry_points: web/index.html
csp: true
- chrome
- $dart2js:
csp: true
and remove content_security_policy from your manifest.json
this should works

Using Polymer in a Dart Chrome App

I am trying to build an app with Dart and Polymer. But polymer scripts seem to be using eval() in web_components/platform.js:32. Has anyone managed to do this? I tried to change CSP but that helped in first place.
Does anyone have a working example?
Regards and Thanks
Robert
EDIT
manifest.json:
{
"name": "Animatr app",
"version": "1",
"author": "Robert Hartung",
"manifest_version": 2,
"icons": {"128": "animatr_icon.png"},
"app": {
"background": {
"scripts": ["background.js"]
}
},
"content_security_policy": "script-src 'self' unsafe-inline;"
}
main.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Animatr app</title>
<link rel="stylesheet" href="animatr_chrome_app.css">
<link rel="import" href="packages/polymer/polymer.html">
</head>
<body>
<script src="packages/chrome/bootstrap.js" defer></script>
<script src="my_chrome_app.dart" type="application/dart;component=1"></script>
</body>
</html>
ERROR:
Refused to evaluate a string as JavaScript because 'unsafe-eval' is not an allowed source of script in the following Content Security Policy directive: "default-src 'self' chrome-extension-resource:". Note that 'script-src' was not explicitly set, so 'default-src' is used as a fallback. (chrome-extension://ofkfcbfhgkoglbgldcdokficikimdjji/packages/web_components/platform.js:32)
Refused to execute inline script because it violates the following Content Security Policy directive: "default-src 'self' chrome-extension-resource:". Either the 'unsafe-inline' keyword, a hash ('sha256-...'), or a nonce ('nonce-...') is required to enable inline execution. Note also that 'script-src' was not explicitly set, so 'default-src' is used as a fallback.
pubspec.yaml:
name: animatr_app
description: A sample Chrome packaged application
dependencies:
chrome: any
polymer: any
transformers:
- chrome
- polymer:
entry_points:
- app/animatr_chrome_app.html
csp: 'true'
The app does not recognize polymer elements correctly.
I have been struggling with the same issue, trying to run the simple wizard generated polymer app (the one with the counter) as a chrome packaged app.
I have finally managed to at least run the javascript built version of it, trying to understand the csp issues.
For many reason, it sounds like it cannot run native as the packaged app is loaded from the file system and not through pub serve. Loading the unpackaged extension from web/build was not working neither as is. The solution was to load xxx.html_bootstrap.dart.precompiled.js instead of xxx.html_bootstrap.js from the generated html file
What i did was:
remove the chrome transformer as the polymer transformer already replace the dart script reference by a javascript script reference
add csp: true in the polymer transformer option (although it did work without it)
to avoid having to change manually the generated html to load the precompiled.js version, I wrote a simple transformer.
I can then load in Chrome (does not have to be Dartium as it is javascript) the unpacked extension from web/build once I run pub build (release mode needed)
I now simply have this warning:
Deprecation: Automatic generation of output for Content Security
Policy is deprecated and will be removed with the next development
release. Use the --csp option to generate CSP restricted output.
which means likely I would have to find a new hack soon...
You can take a look at https://github.com/dart-lang/spark/tree/master/ide for an example Dart Chrome-Packaged-App. They also make heavily use of Polymer.
Maybe this is related https://github.com/Polymer/polymer/issues/252
It seems this is the related Dart bug https://code.google.com/p/dart/issues/detail?id=17409

Resources