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

feat: add experimental cookie encryption support #27524

Merged
merged 18 commits into from May 26, 2021
Merged

Conversation

MarshallOfSound
Copy link
Member

@MarshallOfSound MarshallOfSound commented Jan 27, 2021

This is mostly exploratory but the intention is to provide an Electron Fuse to enable cookie encryption for Electron apps. This has several technical challenges (mostly coming down to hard coded assumptions in Chromium) and the intention is for this WIP PR to remain open while I figure out how to make it work on all three platforms in a generic and sustainable way.

Refs #7073

Platform support as of the moment you're reading this:

  • macOS
  • Windows 7
  • Windows 10
  • Linux (many variants, only ticked when all chromium secret stores are supported)

Migration paths from Un-Encrypted to Encrypted is completely handled by Chromium, it will continue to read un-encrypted cookies but will encrypt-on-write so over time even existing cookies will either expire or be written-over with an encrypted value.

Going the other way (encryp -> unencrypt) is not supported and will be a lossy action (all cookies will be considered invalid or be garbled in HTTP requests). This "revert" story should be documented before landing.

By default Chromium uses values like Chromium Safe Storage to store the encryption keys, Electron will use ${app.getName()} Safe Storage. This results in Electron Safe Storage being the default and packaged apps will have My App Safe Storage.

Notes: Added experimental cookie encryption support behind an Electron Fuse

@MarshallOfSound MarshallOfSound requested a review from a team as a code owner January 27, 2021 23:56
@electron-cation electron-cation bot added the new-pr 🌱 PR opened in the last 24 hours label Jan 27, 2021
@MarshallOfSound MarshallOfSound changed the title feat: add experimental cookie encryption support on macOS feat: add experimental cookie encryption support Jan 27, 2021
@nornagon
Copy link
Member

nornagon commented Feb 1, 2021

Cool stuff :)

Comment on lines +103 to +104
// Only use a persistent prefs store when cookie encryption is enabled as that
// is the only key that needs it
Copy link
Member

Choose a reason for hiding this comment

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

what does the cookie encryption code use this for?

Copy link
Member Author

Choose a reason for hiding this comment

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

On windows the encryption secret is protected with DPAPI and the "protected" encryption key is stored in plain text in Local State on disk.

build/fuses/fuses.json5 Outdated Show resolved Hide resolved
shell/browser/net/system_network_context_manager.cc Outdated Show resolved Hide resolved
scoped_refptr<JsonPrefStore> user_pref_store =
base::MakeRefCounted<JsonPrefStore>(prefs_path);
user_pref_store->ReadPrefs();
prefs_factory.set_user_prefs(user_pref_store);
Copy link
Member

Choose a reason for hiding this comment

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

Does this mean that when cookie encryption is enabled we might store other, non-cookie-encryption-related prefs on disk?

Copy link
Member Author

Choose a reason for hiding this comment

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

I guess so yeah, I would have made it JSON prefs for all cases but that felt like a bit of an overreach for this PR. It would align better with Chromium to do that though

Copy link
Member

Choose a reason for hiding this comment

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

What preferences are in that group? What would we start storing on disk that previously wasn't persisted?

Copy link
Member Author

Choose a reason for hiding this comment

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

My understanding is the only other pref we register into this store is the kProxy pref which is overridden / ignored by the per-browser-context proxy settings later down the line. That pref is never read / set in our code so being in memory vs stored to disk wouldn't appear to have any affected.

Copy link
Member

Choose a reason for hiding this comment

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

The reason we use an in-memory pref for the proxy config is because we reuse proxy config code from //chrome https://github.com/electron/electron/blob/master/patches/chromium/proxy_config_monitor.patch to interact with the proxy service and that relies on reading the configs from a pref store https://source.chromium.org/chromium/chromium/src/+/main:components/proxy_config/pref_proxy_config_tracker_impl.cc, I didn't find the need the flush these values to disk at that time as they are mainly required only to communicate the data between the browser process and the proxy service.

Copy link
Member

Choose a reason for hiding this comment

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

If the pref store is change to a persistent one when cookie encryption is enabled we should also make relevant changes here https://github.com/electron/electron/blob/master/shell/browser/api/electron_api_session.cc#L536

Copy link
Member Author

Choose a reason for hiding this comment

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

@deepak1556 The BrowserProcess prefs store and the BrowserContext prefs store are different and don't need to be aligned afaik. They store things in different locations and having one in memory and one not seems fine to me

Copy link
Member

Choose a reason for hiding this comment

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

You are right, they don't need to be in sync.

Proxy config in BrowserProcess pref store are read by the SystemNetworkContextManager whereas the BrowserContext pref store are read by per-session network contexts.

Copy link
Contributor

@jkleinsc jkleinsc left a comment

Choose a reason for hiding this comment

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

Is there anywhere we can document this feature? It doesn't seem that this feature is very discoverable as is.

Copy link
Member

@samuelmaddock samuelmaddock left a comment

Choose a reason for hiding this comment

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

API LGTM

shell/browser/browser_process_impl.cc Show resolved Hide resolved
@MarshallOfSound
Copy link
Member Author

It doesn't seem that this feature is very discoverable as is.

This is by design, Slack will take the load of testing it and once confidence is higher the plan is to document and flip then later fuse default 👍 Currently this is all very untested and critical to most applications so we're taking it very slowly.

@MarshallOfSound MarshallOfSound merged commit 7984933 into master May 26, 2021
@release-clerk
Copy link

release-clerk bot commented May 26, 2021

Release Notes Persisted

Added experimental cookie encryption support behind an Electron Fuse

@MarshallOfSound MarshallOfSound deleted the cookie-crypto branch May 26, 2021 19:16
MarshallOfSound added a commit that referenced this pull request Jun 2, 2021
* feat: add experimental cookie encryption support on macOS

* chore: fix TODO

* update patches

* feat: make cookie encryption work on windows

* chore: update cookie encryption support comments

* fix: only call OSCrypt::Init on windows

* chore: make cookie encryption work on linux

* Update shell/browser/net/system_network_context_manager.cc

Co-authored-by: Jeremy Rose <jeremya@chromium.org>

* chore: fix lint

* chore: update patches

* chore: update patches to upstreamed variants

* chore: use chrome ::switches constants

* chore: remove bad patch

* build: disable cookie encryption by default

* chore: update patches

* fix: provide std::string to NoDestructor

* chore: fix macos, nodestructor syntax

* build: fix macOS build due to mismatch in DEFINE

Co-authored-by: Electron Bot <electron@github.com>
Co-authored-by: Jeremy Rose <jeremya@chromium.org>
MarshallOfSound added a commit that referenced this pull request Jun 2, 2021
* feat: add experimental cookie encryption support on macOS

* chore: fix TODO

* update patches

* feat: make cookie encryption work on windows

* chore: update cookie encryption support comments

* fix: only call OSCrypt::Init on windows

* chore: make cookie encryption work on linux

* Update shell/browser/net/system_network_context_manager.cc

Co-authored-by: Jeremy Rose <jeremya@chromium.org>

* chore: fix lint

* chore: update patches

* chore: update patches to upstreamed variants

* chore: use chrome ::switches constants

* chore: remove bad patch

* build: disable cookie encryption by default

* chore: update patches

* fix: provide std::string to NoDestructor

* chore: fix macos, nodestructor syntax

* build: fix macOS build due to mismatch in DEFINE

Co-authored-by: Electron Bot <electron@github.com>
Co-authored-by: Jeremy Rose <jeremya@chromium.org>
@trop
Copy link
Contributor

trop bot commented Jun 2, 2021

@MarshallOfSound has manually backported this PR to "14-x-y", please check out #29492

@trop trop bot added the in-flight/14-x-y label Jun 2, 2021
@trop
Copy link
Contributor

trop bot commented Jun 2, 2021

@MarshallOfSound has manually backported this PR to "13-x-y", please check out #29493

MarshallOfSound added a commit that referenced this pull request Jun 2, 2021
* feat: add experimental cookie encryption support on macOS

* chore: fix TODO

* update patches

* feat: make cookie encryption work on windows

* chore: update cookie encryption support comments

* fix: only call OSCrypt::Init on windows

* chore: make cookie encryption work on linux

* Update shell/browser/net/system_network_context_manager.cc

Co-authored-by: Jeremy Rose <jeremya@chromium.org>

* chore: fix lint

* chore: update patches

* chore: update patches to upstreamed variants

* chore: use chrome ::switches constants

* chore: remove bad patch

* build: disable cookie encryption by default

* chore: update patches

* fix: provide std::string to NoDestructor

* chore: fix macos, nodestructor syntax

* build: fix macOS build due to mismatch in DEFINE

Co-authored-by: Electron Bot <electron@github.com>
Co-authored-by: Jeremy Rose <jeremya@chromium.org>

Co-authored-by: Electron Bot <electron@github.com>
Co-authored-by: Jeremy Rose <jeremya@chromium.org>
MarshallOfSound added a commit that referenced this pull request Jun 3, 2021
* feat: add experimental cookie encryption support (#27524)

* feat: add experimental cookie encryption support on macOS

* chore: fix TODO

* update patches

* feat: make cookie encryption work on windows

* chore: update cookie encryption support comments

* fix: only call OSCrypt::Init on windows

* chore: make cookie encryption work on linux

* Update shell/browser/net/system_network_context_manager.cc

Co-authored-by: Jeremy Rose <jeremya@chromium.org>

* chore: fix lint

* chore: update patches

* chore: update patches to upstreamed variants

* chore: use chrome ::switches constants

* chore: remove bad patch

* build: disable cookie encryption by default

* chore: update patches

* fix: provide std::string to NoDestructor

* chore: fix macos, nodestructor syntax

* build: fix macOS build due to mismatch in DEFINE

Co-authored-by: Electron Bot <electron@github.com>
Co-authored-by: Jeremy Rose <jeremya@chromium.org>

* chore: update patches

Co-authored-by: Electron Bot <electron@github.com>
Co-authored-by: Jeremy Rose <jeremya@chromium.org>
@theogravity
Copy link
Contributor

It's unclear to me what the behavior is when you have support enabled and the user denies the prompt for keychain access in MacOS.

Do the cookies get stored unencrypted then? Is there a way for us to know that the user has denied this access?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
semver/minor backwards-compatible functionality
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

7 participants