Electron Apps Are Getting Safer to Use

Electron is now poised for the enterprise

by Joe Honton

Electron desktop applications are created using technologies that are familiar to millions of software developers. This makes for a low entry barrier, and accounts for much of its appeal. Getting started is easy. Anyone familiar with Node.js can bootstrap a Hello World! desktop app with minimal fuss.

Of course there's also the other big draw: that the same codebase can be used to simultaneously target Windows, Mac and Linux. It all adds up to a compelling case for taking a closer look.

But creating a real Electron app is not for the faint of heart. Transforming that initial Hello World! into something fast and safe takes effort. Thankfully, performance and security are the big news items for Electron in 2020.

2019 — An Inflection Year

Several significant events occurred over the past year, bringing about an inflection point in the project. Last year's journey passed these major milestones:

  • Regular releases began in earnest, with version 4.0 kicking off the new year, version 5.0 arriving in April, version 6.0 in July, and version 7.0 in October.
  • In March, Electron adopted a governance structure, to formally lay out the rules of the road and to help make forward progress easier to achieve.
  • In November, a fresh build process was unveiled by Charles Kerr and team, which dramatically shortens the time it takes to rebuild Electron when its dependencies (Node.js, V8, and Chromium) change.
  • In December, Electron was added to the OpenJS Foundation as an incubating project, signaling to the JavaScript community at large that the project is here to stay.

It's beginning to feel like the joy ride of 2014 has settled into a more cadenced long haul.

Security Improvements

Some people know that the recently release Brave browser began life as an experimental Electron project. After giving it a serious try, the Brave team eventually realized that no amount of lock-down code was going to allow them to safely access arbitrary URLs which could potentially contain malicious code. The lesson for the rest of the Electron community was clear: use Electron's embedded Chromium browser windows to display locally hosted pages only.

For those developers who simply couldn't resist the temptation to access remote URLs, the advice was a bit more complicated: make sure web pages have an HTTP content security policy that restricts JavaScript from being obtained through unsafe channels. Content security policies are not a part of every developer's skill set, so there's a bit of learning ahead for anyone wanting to do this correctly.

The scary part in all of this is that Electron's embedded Node.js library gives developers full access to the desktop's file system and networking stack. This is what distinguishes Electron desktop applications from simple browser apps. So to reduce the risk of malicious code running amok, developers can enable the sandbox option for any browser window that doesn't need Node.js. Sandboxing works at the level of the host operating system. It's the sledgehammer approach to lock-downs.

Developers who need Node.js and decide to keep the sandbox option off, can still play it safe by properly setting the nodeIntegration option.

  • When creating a browser window that accesses locally hosted documents which use only locally hosted resources (scripts, style sheets, images or fonts), nodeIntegration can safely be set to true, allowing Node.js library calls.
  • On the other hand, when creating a browser window that may access arbitrary remote URLs, nodeIntegration must always be set to false, blocking Node.js library calls.

When select access to Node.js is still needed in a browser window with nodeIntegration off, developers can make use of a preload script. With this type of architecture, a separate JavaScript module is executed just before a browser window is created. That module has access to Node.js throughout the browser window's lifetime, and can act as a custom-built proxy API. As long as the proxy only passes through simple values, and not Node.js objects, the preload script can safely get and set file system and operating system values on behalf of the browser window.

For even more safety when accessing remote content, the contextIsolation option can be set to true. This option will force the creation of a separate JavaScript world for each browser window. Context isolation stops bad actors from mucking around with JavaScript's prototype chain in an untrusted browser window, in order to surreptitiously gain control over trusted code in a sibling browser window.

Developers just starting with Electron may not fully appreciate the importance of these options, and may inadvertently make poor choices in their haste to get a working prototype. To help with this, Luca Carettoni of Doyensec has created an open source tool with a pun filled name — Electronegativity. Think of it as a security auditing tool. It works by scanning a project's HTML DOM and JavaScript AST to find potential vulnerabilities.

The Curious Proposal to Deprecate "Remote"

Electron is an open source project, and unlike many such projects it has no big corporate sponsor. Work is carried out by developers scattered across the globe working on projects with very different goals. So it should come as no surprise that contributors have focused on diverse needs.

Thankfully, one of those needs is better performance. To that end, at the recent 2020 Covalence Conference it was announced that the much used remote module would be deprecated in Electron version 9.0, and removed entirely in version 10.0. This came as a surprise. Somehow I had missed seeing Jeremy Apthorp's previously published article Electron's "Remote" module considered harmful.

To understand the implications of this, newcomers need to appreciate that Electron applications have a split personality. On one side there's the application's main process, which is responsible for kick-starting everything. On the other side there are the application's renderer processes. The two communicate using inter-process communication (IPC).

The key to mastering Electron development is to understand how to use ipcMain and ipcRenderer to coordinate everything. This is where the remote module comes in handy. It makes IPC calls from a renderer process to the main process super simple, allowing mere mortals to get more done.

In all of the Electron apps I'm involved with remote.getGlobal() is used strategically and effectively. It works as expected every time.

The reasoning behind the vilification of remote, and my own counter-points, are:

  • Argument: It takes 0.1ms per IPC call. Counterpoint: This is peanuts. In the blink of an eye (at a frame rate of 16ms per screen refresh) 160 IPC calls could be made.
  • Argument: It could lead to race conditions when used improperly. Counterpoint: Setting up callback listeners before execution eliminates this class of problems.
  • Argument: Remote objects are proxied, and lose their prototype chain. Counterpoint: Proper deserialization and casting to the correct object type allows the result to be used without surprises.
  • Argument: It's a security vulnerability waiting to happen. Counterpoint: This is not a germane argument. PNG images coming from the main process could have deployed their malicious payloads irrespective of any IPC call.

I personally think this is taking performance a bit too far, and hope that the plan to deprecate the remote module isn't carried out. Still, I do appreciate the attention to detail. It's nice to know that Electron performance tuning has reached a level where 0.1ms is considered important.

Poised for the Enterprise

One thing I noticed at this year's conference was the trend towards using Electron for enterprise desktop applications, especially those targeting Windows users. Amid all the hullabaloo surrounding Electron's cross-platform capabilities, the point was missed that you don't have to target all three. I spoke with numerous people at the conference who were specifically limiting their development efforts to optimize for the Windows audience. Terry Thorsen, of ChartIQ presented the case well.

The fact that C++ programmers are becoming a scarce breed is no secret. And the rise in JavaScript-first developers is equally apparent. So it should come as no surprise that Electron is poised to give Microsoft a run for their money. Older MFC applications looking for a fresh face with gorgeous styling are especially good candidates for rewriting with Electron. And my money's on C# and Visual Basic taking hits as well.

But to really pull this off the Electron community will need to start soliciting feedback directly from enterprise users, and putting their needs on the roadmap.

A Roadmap for 2020

I haven't seen a roadmap for 2020 and beyond, but if the release cadence of last year is kept up we can expect to see versions 8, 9, 10 and 11 over the next twelve months. My personal wish list includes:

  • Better application-layer support for inter-process communication (IPC). Since we can't use events or callbacks to cross the main/renderer divide, a large part of every Electron application is handling the scaffolding for passing data around. Currently everyone has to roll their own.
  • Better support for application level variables. Since renderers need to get and set application state, it makes sense to have some dedicated state object that both the main process and the separate renderers can access. Presently this is all done with remote.getGlobal(). It's primitive and gets the job done, but I'd vote for something more sophisticated.
  • Tree-shaking. Electron apps are bloated with code that never gets called. A welcome addition to the final asar build process would be a step that analyzed which files could be jettisoned. I realize that this might be a time consuming process, but I for one would use it without grumbling.
  • An Electron lint tool. As the project grows, better ways of doing things will be discovered, and older ways deprecated. Having a tool to scan our application and suggest ways to improve it using these new features would make everyone's app faster and safer.

Electron Apps Are Getting Safer to Use — Electron is now poised for the enterprise