electron: systemPreferences.askForMediaAccess(mediaType) causes app to crash in macOS Mojave

Preflight Checklist

  • I have read the Contributing Guidelines for this project.
  • I agree to follow the Code of Conduct that this project adheres to.
  • I have searched the issue tracker for an issue that matches the one I want to file, without success.

Issue Details

  • Electron Version:
    • 5.0.7
  • Operating System:
    • MacOS 10.14.5 (Mojave)
  • Last Known Working Electron version:
    • N/A (Same issue in version 4.0.0, which introduced askForMediaAccess())

Expected Behavior

User should be prompted to grant microphone access.

Actual Behavior

App crashes with the following error report: https://gist.github.com/fgladisch/04f1c62b46dae37d55f05d001af7d7ee

To Reproduce

The app crashes as soon as this line is called:

const success = await systemPreferences.askForMediaAccess("microphone");

We have included a NSMicrophoneUsageDescription in our Info.plist as described here.

Here is the full function we use to request media access. It is called when the Permission Request Handler is invoked with the media permission. The app does not reach the catch Block, so the error is not logged. We tested this behaviour on 3 different machines.

async function askForMediaAccess(): Promise<boolean> {
  try {
    if (platform !== "darwin") {
      return true;
    }

    const status = await systemPreferences.getMediaAccessStatus("microphone");
    log.info("Current microphone access status:", status);

    if (status === "not-determined") {
      const success = await systemPreferences.askForMediaAccess("microphone");
      log.info("Result of microphone access:", success.valueOf() ? "granted" : "denied");
      return success.valueOf();
    }

    return status === "granted";
  } catch (error) {
    log.error("Could not get microphone permission:", error.message);
  }
  return false;
}

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Reactions: 10
  • Comments: 16 (4 by maintainers)

Most upvoted comments

@fgladisch

The TCC log indicates that the entitlement is correctly set. The app crashes regardless. This seems to be a bug affecting Electron under MacOS 10.14.5 or higher.

After adding the following entitlement my app stopped crashing just after start:

    <key>com.apple.security.cs.allow-unsigned-executable-memory</key>
    <true/>

It seems that some part of Electron application (the framework itself or some part of the bundled Chromium) generates runtime code and puts it in the writeable memory area, that’s why application immediately crashes with EXC_BAD_ACCESS (Code Signature Invalid), because code generated in runtime cannot be signed.

@MarshallOfSound @codebytere I believe it should be noted somewhere in the documentation, that any Electron application to be built with hardenedRuntime option (which is turned on by default in the latest electron-builder) requires some specific entitlements additionally to yours (camera, audio-input etc), otherwise the application will crash immediately, even if it does nothing. I have spent several hours of debugging to realize it.

The whole working entitlements.mac.plist for my use case:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
  <dict>
    <key>com.apple.security.cs.allow-jit</key>
    <true/>
    <key>com.apple.security.cs.allow-unsigned-executable-memory</key>
    <true/>
    <key>com.apple.security.cs.allow-dyld-environment-variables</key>
    <true/>
    <key>com.apple.security.device.audio-input</key>
    <true/>
    <key>com.apple.security.device.camera</key>
    <true/>
  </dict>
</plist>

Also to be able to use camera and microphone in your application package.json for using with electron-builder should contain the following additional information (I leave it here for those who try to find a solution to be able to record video and audio in Electron 4, 5 and 6 under Mac OS 10.14+):

{
  "build": {
    "mac": {
      "entitlements": "build/entitlements.mac.plist",
      "extendInfo": {
        "NSCameraUsageDescription": "This app requires camera access to record video.",
        "NSMicrophoneUsageDescription": "This app requires microphone access to record audio."
      }
    }
  }
}

Without this information your application will be killed by OS after call systemPreferences.askForMediaAccess()

Update 2: Disabling “Hardened Runtime” through electron-builder fixes the crash above:

{
  "mac": {
    "hardenedRuntime": false
  }
}

Everything seems to work now, including the microphone access prompt with the string set in NSMicrophoneUsageDescription.

How can you notarize without hardened runtime?

steps to reproduce what i’m talking about in previous comment:

  • npx create-electron-app not-working-media-access
  • in the index.js -> createWindow function insert code fragment 1
  • run application with the npm start

code fragment 1

systemPreferences.askForMediaAccess('microphone').then((isAllowed) => {
      console.log('isAllowed', isAllowed);
  });

question on stackoverflow: https://stackoverflow.com/questions/58290668/electron-osx-systempreferences-askformediaaccess-crashes-app

@fgladisch Please check the Hardened Runtime documentation for entitlements --> https://developer.apple.com/documentation/bundleresources/entitlements?language=objc

If you want the ability to access the microphone you need to add the com.apple.security.device.audio-input entitlement if you have hardened runtime enabled

__CRASHING_DUE_TO_PRIVACY_VIOLATION__ seems to be the root cause here, indicating a permissions issue. i’ll try to dig into this, and @miniak may also know more here.