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

fix!: change enableRemoteModule to .enable() for electron@14 #72

Merged
merged 9 commits into from
Sep 14, 2021

Conversation

artus9033
Copy link
Contributor

@artus9033 artus9033 commented Sep 1, 2021

BREAKING CHANGE: This removes the enableRemoteModule option in favor of a new .enable() method for enabling the remote module on a particular WebContents. See https://github.com/electron/remote/blob/main/docs/migration-2.md for migration instructions.

Fixes #71

@artus9033 artus9033 changed the title Fix to work with electron@14, maintaining backwards compatibility fix: Fix to work with electron@14, maintaining backwards compatibility Sep 1, 2021
@artus9033 artus9033 changed the title fix: Fix to work with electron@14, maintaining backwards compatibility fix: electron@14 breaking changes (enableRemoteModule), maintaining backwards compatibility Sep 1, 2021
Copy link
Member

@nornagon nornagon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please undo the unrelated changes to README.md 🙇‍♂️

I think this is a reasonable approach, but I wonder if there is some way to allow users of this module to enable the remote module for only some WebContents. Perhaps some new api like

require("@electron/remote/main").permit(webContents)

?

@artus9033
Copy link
Contributor Author

Sorry, it seems like auto-formatting kicked in - now the unrelated parts of README are back in the original state

@artus9033
Copy link
Contributor Author

I think this is a reasonable approach, but I wonder if there is some way to allow users of this module to enable the remote module for only some WebContents. Perhaps some new api like

require("@electron/remote/main").permit(webContents)

?

That is true, indeed it would be sensible to restrict remote to selected WebContents. As there seems to be no way to operate on the WebPreferences anymore, perhaps even re-using the original isRemoteModuleEnabledCache and delegating set() manipulation to the new permit API would be an idea, it wouldn't require too much changes.

@nornagon
Copy link
Member

nornagon commented Sep 1, 2021

@artus9033 yeah, that makes sense! Do you want to take a stab at it?

@artus9033
Copy link
Contributor Author

artus9033 commented Sep 1, 2021

Sure, just testing the implementation now - a commit will fly in in a moment

@artus9033
Copy link
Contributor Author

Done, this is definitely more solid than the first approach.
I guess it would be nice to cover the feature with tests with electron@14 - if that would be helpful, I could do that this week.

@nomagick
Copy link

nomagick commented Sep 2, 2021

This will break code on Electron >= v14 that still have enableRemoteModule set true , who might just not been using Typescript and have survived this change in typings.

@nomagick
Copy link

nomagick commented Sep 2, 2021

And the .permit() API is kind of ugly.

I suggest adding a global option like .initialize({ permissive: true }) in the same time.

And keep the enableRemoteModule check on all versions for backward compatibility.

@kku39
Copy link

kku39 commented Sep 2, 2021

@nomagick

This will break code on Electron >= v14 that still have enableRemoteModule set true , who might just not been using Typescript and have survived this change in typings.

I think it doesn't make sense.

I tested code on Electron >= v14 that still have enableRemoteModule set true, but @electron/remote raised Set {enableRemoteModule: true} in WebPreferences to enable it. .

It seems that enableRemoteModule is omitted from webPreferences on Electron >= v14 even if user set it, so there's no way to let them survive.

@artus9033
Copy link
Contributor Author

artus9033 commented Sep 2, 2021

And the .permit() API is kind of ugly.

I suggest adding a global option like .initialize({ permissive: true }) in the same time.

And keep the enableRemoteModule check on all versions for backward compatibility.

Although the permissive option might be an option to discuss (though it brings in potential security issues), leaving space for untyped and, most importantly, removed options in external APIs is unacceptable. That is why semantic versioning contains the major component, which indicates breaking changes.
Users upgrading from older major releases to 14.X.X should expect that some APIs might have changed and take the effort to look them up in electron's changelog. Then, they would definitely notice that enableRemoteModule has been removed. I see no point why the project should pretend electron's API has not changed.

@nomagick
Copy link

nomagick commented Sep 2, 2021

@nomagick

This will break code on Electron >= v14 that still have enableRemoteModule set true , who might just not been using Typescript and have survived this change in typings.

I think it doesn't make sense.

I tested code on Electron >= v14 that still have enableRemoteModule set true, but @electron/remote raised Set {enableRemoteModule: true} in WebPreferences to enable it. .

It seems that enableRemoteModule is omitted from webPreferences on Electron >= v14 even if user set it, so there's no way to let them survive.

It does work for me in browser process at least.
I currently walk around this issue by disabling type check on WebPreference.

Copy link
Member

@nornagon nornagon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems reasonable! Would be great to test.

Ideally, this approach should also work on electron@13 and earlier so people can upgrade @electron/remote to the new approach while still using an older version of electron, to allow for future-proofing.

README.md Outdated Show resolved Hide resolved
README.md Outdated Show resolved Hide resolved
@artus9033
Copy link
Contributor Author

Sure, this is prepared to be fully working with older releases. I tested it locally on older versions and it fully maintains old API compatibility.

In the next few days I can try to port the tests to the newest versions. @nornagon, should I put them here in this PR or is this one finished for now and the tests would be a separate PR?

@nomagick
Copy link

nomagick commented Sep 3, 2021

@artus9033 @nornagon
You do realize that from the Javascript perspective, there were no bug or any issues at this moment.
From the Javascript perspective @electron/remote has always been checking enableRemoteModule on Webpreferences.
And stop doing so guarantees 100% of currently working code to break.

It's not electron making breaking changes, but @electron/remote that is about to make one.

At least make that a major release, please.

Co-authored-by: Jeremy Rose <nornagon@nornagon.net>
@nornagon
Copy link
Member

nornagon commented Sep 7, 2021

And stop doing so guarantees 100% of currently working code to break.

I think this is a reasonable point.

Unfortunately we have to compromise somehow here. In Electron 14.x, WebPreferences no longer record unknown parameters, which is what was allowing enableRemoteModule to continue to work even though Electron didn't officially support the parameter. So we have to make some sort of change. Our options are:

  1. Disable remote by default on all WebContents, and provide some other way of enabling it for specific WebContents (i.e. this PR's approach).
  2. Enable remote by default on all WebContents, and (optionally) provide some way of disabling it for specific WebContents.

The former approach is a more secure approach, as it means that access to @electron/remote won't be inadvertently granted to content which shouldn't be allowed access to it when an app upgrades to the new version of Electron and @electron/remote. However, their usage of @electron/remote would be broken by the upgrade.

The latter is a more permissive approach, allowing apps to continue to function with minimal changes, but potentially introducing security issues (i.e. granting @electron/remote access to contents which shouldn't have that access).

I'm not sure how common it is in apps which use @electron/remote to have multiple WebContents, some of which have access to @electron/remote and others which don't. There are a lot of ways to create WebContents that aren't as obvious as new BrowserWindow (e.g. window.open, opening devtools, or using <webview>), so auditing one's app for whether or not it can possibly open a WebContents that shouldn't have remote access can be challenging.

I'm also hesitant to publish an upgrade, especially a minor-version bump, which would further reduce the security of apps using this module. On the one hand, @electron/remote has big warnings all over the box that say "don't use this, it's insecure", so maybe reducing the security a bit is not such a big deal, because users of this module have accepted the trade-off in security already. On the other hand, users might have accepted that trade-off because they know they can isolate the risk to only specific parts of their app, and making the remote module default-enabled would betray that expectation.

Finally, given that with Electron 14, currently @electron/remote is entirely broken, it should be fairly obvious to users that they will need to change something about their usage of @electron/remote.

For the above reasons, I think the best way forward is to do the following:

  1. Publish @electron/remote@2.0.0, removing the enableRemoteModule WebPreference and adding the new permit API.
  2. Write a migration guide explaining how to switch from enableRemoteModule to permit.
  3. Publish @electron/remote@1.2.2 with a check for Electron >=14. If Electron >= 14 is detected, throw an error when require("@electron/remote/main").initialize() is called, with a detailed explanation and a link to the migration guide.

I think this strikes the best balance between security and convenience. We can gently guide users towards the appropriate fixes, and hopefully make it as smooth as possible for them to change to the new API, and also avoid accidentally creating new security holes.

@nornagon
Copy link
Member

nornagon commented Sep 7, 2021

I've added a draft migration guide in #74. In that guide I changed the name of the function from permit to enable, so we should reflect that change here. I think it's helpful to use the word enable since that's the same word that was previously used in enableRemoteModule.

@artus9033
Copy link
Contributor Author

artus9033 commented Sep 7, 2021

@nornagon that sounds perfectly reasonable. As an example, in an application I created (which is publicly available on one of my repos), I use separate BrowserWindows for docs and user manual, both leading to GH pages, and utilize window.open API for opening external links to libraries' landing pages & other resources. Having to remember to disable the remote module each time there would be a nightmare, potentially being a security concern.

I've just renamed the permit function to enable, also moving the README descriptions for >= 14 above the now-legacy < 14 instructions.

@MatanYemini
Copy link

MatanYemini commented Sep 13, 2021

Hi --

Why this merge is blocked?

@nornagon @artus9033

I really need the update for electron 14 (since it updates things that I am using).

Please let me know if you want me to do that, or just adjust the relevant things?

Thanks.

@nornagon nornagon changed the title fix: electron@14 breaking changes (enableRemoteModule), maintaining backwards compatibility fix: change enableRemoteModule to .enable() for electron@14 Sep 14, 2021
@nornagon nornagon changed the title fix: change enableRemoteModule to .enable() for electron@14 fix!: change enableRemoteModule to .enable() for electron@14 Sep 14, 2021
src/main/server.ts Outdated Show resolved Hide resolved
@nornagon nornagon merged commit fd928e5 into electron:main Sep 14, 2021
nornagon added a commit that referenced this pull request Sep 14, 2021
BREAKING CHANGE: This removes the `enableRemoteModule` option in favor of a new `.enable()` method for enabling the remote module on a particular WebContents. See https://github.com/electron/remote/blob/main/docs/migration-2.md for migration instructions.

This is an empty commit for forcing a release after a semantic-release
failure in fd928e5.
@electron-bot
Copy link

🎉 This PR is included in version 2.0.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

@noseratio
Copy link

noseratio commented Sep 22, 2021

With Electron 14.0.1, require("@electron/remote/main").enable(window.webContents) doesn't work for windows created from Renderer process. It does works for Main process, but from Renderer, this call does nothing and I'm getting @electron/remote is disabled for this WebContents. Call require("@electron/remote/main").enable(webContents) to enable it..

Am I missing something, @nornagon? I wouldn't a breaking change in a point release, and this code worked just fine with v14.0.0. Thanks for any help.

Updated, figured it out, it has to be remote.require("@electron/remote/main").enable(window.webContents) for Renderer, and vs require("@electron/remote/main").enable(webContents) for Main.

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

Successfully merging this pull request may close these issues.

Not work with electron@14 since enableRemoteModule removed
7 participants