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 Secure Keyboard Entry APIs in macOS #20678

Merged
merged 6 commits into from May 21, 2020

Conversation

mtgto
Copy link
Contributor

@mtgto mtgto commented Oct 22, 2019

Description of Change

Add two APIs to app to control Secure Keyboard Entry.

In macOS, there is a way to protect from other processes listen keyboard input event.
https://developer.apple.com/library/archive/technotes/tn2150/_index.html

To enable it, we call EnableSecureEventInput, which available since Mac OS X 10.3.

This functions helps the apps become more security like bitwarden/desktop#298

app.setSecureKeyboardEntryEnabled(enabled) protects your application (your process) from listening keyboard input events. You have to disable before quit application.

app.isSecureKeyboardEntryEnabled() returns true if you already called app.setSecureInputEnabled(true).

To confirm your application is protected or not, below command is helpful.

ioreg -l -w 0 | grep kCGSSessionSecureInputPID

I write sample Electron app to test this PR is working. (2020-05-17 added)
https://github.com/mtgto/electron-secure-event-input-sample

I test with Swift-Keylogger whether this API protect from keylogger.
Here is my electron sample.

Password textfield is already protected by Chromium, but plain textfield is not.
I confirmed this API protect plain textfield from keylogger.

Here is the list of other open source softwares use the API.

Chromium
https://cs.chromium.org/chromium/src/ui/base/cocoa/secure_password_input.mm

iTerm2
https://github.com/gnachman/iTerm2/blob/master/sources/iTermSecureKeyboardEntryController.m

Checklist

npm test failed in my environment:

error /Users/user/work/js/electron/electron-gn/src/electron/spec/node_modules/is-valid-window: Command failed.
Exit code: 1
Command: node-gyp rebuild
Arguments:
Directory: /Users/user/work/js/electron/electron-gn/src/electron/spec/node_modules/is-valid-window
Output:
gyp: /Users/user/work/js/electron/electron-gn/src/out/Debug/gen/node_headers/common.gypi not found (cwd: /Users/user/work/js/electron/electron-gn/src/electron/spec/node_modules/is-valid-window) while reading includes of binding.gyp while trying to load binding.gyp

Release Notes

Notes: add app.isSecureInputEnabled() and app.setSecureInputEnabled(enabled) to manage Secure Keyboard Entry in macOS.

@welcome
Copy link

welcome bot commented Oct 22, 2019

💖 Thanks for opening this pull request! 💖

We use semantic commit messages to streamline the release process. Before your pull request can be merged, you should update your pull request title to start with a semantic prefix.

Examples of commit messages with semantic prefixes:

  • fix: don't overwrite prevent_default if default wasn't prevented
  • feat: add app.isPackaged() method
  • docs: app.isDefaultProtocolClient is now available on Linux

Things that will help get your PR across the finish line:

  • Follow the JavaScript, C++, and Python coding style.
  • Run npm run lint locally to catch formatting errors earlier.
  • Document any user-facing changes you've made following the documentation styleguide.
  • Include tests when adding/changing behavior.
  • Include screenshots and animated GIFs whenever possible.

We get a lot of pull requests on this repo, so please be patient and we will get back to you as soon as we can.

@electron-cation electron-cation bot added the new-pr 🌱 PR opened in the last 24 hours label Oct 22, 2019
mtgto added a commit to mtgto/electron that referenced this pull request Oct 22, 2019
Copy link
Contributor

@miniak miniak left a comment

Choose a reason for hiding this comment

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

There are several incorrectly phrased sentences in the documentation.

void Browser::SetSecureInputEnabled(bool enabled) {
// See
// https://developer.apple.com/library/content/technotes/tn2150/_index.html
if (enabled) {
Copy link
Contributor

Choose a reason for hiding this comment

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

calling setSecureInputEnabled() with the same value twice should have no effect IMO.

@electron-cation electron-cation bot removed the new-pr 🌱 PR opened in the last 24 hours label Oct 23, 2019
@mtgto
Copy link
Contributor Author

mtgto commented Oct 23, 2019

@miniak I apologize for wasting your time for my first PR. I almost rewrote.

There are several changes since first pull request:

  1. Rename API
    • User easily realize what the APIs are. The name is from menuitem of Terminal.app.
  2. Use ScopedPasswordInputEnabler in Chromium instead of call EnableSecureEventInput() by API itself
    • While debugging, I found app.SetSecureKeyboardEntryEnabled(true) causes crash Electron. This is because Chromium already use Secure Keyboard Entry in password textfield.
    • Please grep with ScopedPasswordInputEnabler in textfield.cc
  3. Rewrite API doc

void Browser::SetSecureKeyboardEntryEnabled(bool enabled) {
if (enabled) {
password_input_enabler_ =
std::make_unique<ui::ScopedPasswordInputEnabler>();
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@mtgto mtgto requested a review from miniak October 28, 2019 14:07
@zcbenz
Copy link
Member

zcbenz commented Jan 13, 2020

@miniak Can you take another look at this?

docs/api/app.md Outdated

By default this API will return `false`.

On _Linux_ and _Windows_, this API will return `false`.
Copy link
Contributor

@miniak miniak May 9, 2020

Choose a reason for hiding this comment

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

This API should probably be only exposed on Mac.

docs/api/app.md Outdated

**Note:** Enable only when it is needed and disable it when it is no longer needed.

On _Linux_ and _Windows_, this API will do nothing.
Copy link
Contributor

Choose a reason for hiding this comment

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

The same here, the method documentation says it's only available on Mac.

@@ -259,6 +263,11 @@ class Browser : public WindowListObserver {

void RemoveObserver(BrowserObserver* obs) { observers_.RemoveObserver(obs); }

// Returns whether secure input is enabled
bool IsSecureKeyboardEntryEnabled();

Copy link
Contributor

Choose a reason for hiding this comment

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

why the space?

Copy link
Contributor

@miniak miniak left a comment

Choose a reason for hiding this comment

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

The implementation is good now, however these APIs should only be exposed on Mac IMO as they do nothing on other platforms.

@mtgto
Copy link
Contributor Author

mtgto commented May 15, 2020

Thanks for your review. I'll fix this weekend.

mtgto added 4 commits May 17, 2020 10:04
Add methods:
- app.isSecureInputEnabled()
- app.setSecureInputEnabled(enabled)

These enable to prevent other process listens keyboard input events.
@mtgto mtgto force-pushed the feat_darwin_secure_keyboard_entry branch from efe9c2c to 30f98fd Compare May 17, 2020 14:12
@mtgto
Copy link
Contributor Author

mtgto commented May 17, 2020

@zcbenz
Copy link
Member

zcbenz commented May 18, 2020

Can you fix the lint error?

$ node ./script/lint.js && npm run lint:clang-format && npm run lint:docs
 
shell/browser/browser_mac.mm:440:  Add #include <memory> for make_unique<>  [build/include_what_you_use] [4]
 
Total errors found: 1
 

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.

Would it be possible to write a test for this?

In particular, I'm worried that this might interact poorly with the existing password field security, where calling setSecureKeyboardEntryEnabled(true), then focusing a password field, then focusing out would result in the secure keyboard entry being disabled.

@jkleinsc
Copy link
Contributor

@electron/wg-api reviewed on May-18-2020.

@mtgto
Copy link
Contributor Author

mtgto commented May 19, 2020

@nornagon

Would it be possible to write a test for this?

added. 619319f

In particular, I'm worried that this might interact poorly with the existing password field security, where calling setSecureKeyboardEntryEnabled(true), then focusing a password field, then focusing out would result in the secure keyboard entry being disabled.

I try to reproduce it by using sample app, but I can't.
https://github.com/mtgto/electron-secure-event-input-sample
Please tell me the way and your environment.

@nornagon
Copy link
Member

@nornagon

Would it be possible to write a test for this?

added. 619319f

Thanks. I was hoping that it would be possible to test that the underlying feature was working—i.e. that it was protecting input from being read by other applications—but that seems hard and this test at least exercises the code path.

In particular, I'm worried that this might interact poorly with the existing password field security, where calling setSecureKeyboardEntryEnabled(true), then focusing a password field, then focusing out would result in the secure keyboard entry being disabled.

I try to reproduce it by using sample app, but I can't.
https://github.com/mtgto/electron-secure-event-input-sample
Please tell me the way and your environment.

Thanks, your test looks good. Looking at the underlying code in chromium it looks like there's a counter to track how many ScopedPasswordInputEnablers are present, so it should be fine.

@jkleinsc jkleinsc merged commit 7b55a70 into electron:master May 21, 2020
@welcome
Copy link

welcome bot commented May 21, 2020

Congrats on merging your first pull request! 🎉🎉🎉

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

Successfully merging this pull request may close these issues.

None yet

5 participants