Electron-osx-sign: deny network-bind after signing the app

Created on 9 Jun 2017  路  5Comments  路  Source: electron/electron-osx-sign

Hi,

I'm using the last version of electron (v1.6.10) and electron-osx-sign (v0.4.6). Everything works well, but when I sign with electron-osx-sign and I execute the signed app, it opens and closes immediately after.

The Console app of MacOs returns these logs:

SandboxViolation: Myapp(41701) deny network-bind /private/var/folders/sd/123456/T/com.electron.myapp/S/SS
Violation:       deny network-bind /private/var/folders/sd/123456/T/com.electron.myapp/S/SS 
Process:         Myapp [41701]
Path:            /Users/me/Projects/Myapp/out/Myapp-mas-x64/Myapp.app/Contents/MacOS/Myapp
Load Address:    0x10d918000
Identifier:      com.electron.myapp
Version:         1.0.0 (1.0.0)
Code Type:       x86_64 (Native)
Parent Process:  launchd [1]
Responsible:     /Users/me/Projects/Myapp/out/Myapp-mas-x64/Myapp.app/Contents/MacOS/Myapp [41701]
User ID:         501

Date/Time:       2017-06-09 22:42:38.991 GMT+2
OS Version:      Mac OS X 10.12.5 (16F73)
Report Version:  8

Thread 0 (id: 4788715):

Thread 1 (id: 4788763):

Thread 2 (id: 4788764):

Thread 3 (id: 4788765):

Thread 4 (id: 4788768, WorkerPool/15363):

Thread 5 (id: 4788769, WorkerPool/15875):

Binary Images:

MetaData: {"build":"Mac OS X 10.12.5 (16F73)","action":"deny","target":["private","var","folders","sd","123456","T","com.electron.myapp","S","SS"],"hardware":"Mac","platform_binary":"no","profile":"unknown","process":"Myapp","op":"network-bind"}

I used electron-packager like this:

$ electron-packager . \
  "Myapp" \
  --asar \
  --overwrite \
  --platform=mas \
  --appBundleId="com.electron.myapp" \
  --appVersion="1.0.0" \
  --version="1.6.10" \
  --arch=x64 \
  --icon=./resources/app-icon/mac/Icon.icns \
  --prune=true \
  --out=out \
  --extendInfo=./resources/mac/Info.plist

Info.plist

<?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>ElectronTeamID</key>
  <string>my_team_id_from_distribution_certificates</string>
</dict>
</plist>

I used this guide https://mintkit.net/electron-userland/electron-osx-sign/guide/:

$ electron-osx-sign "./out/Myapp-mas-x64/Myapp.app" \
 --platform=mas \
 --type=development \
 --identity="Mac Developer: My_firstname My_lastname (my_team_id_from_development_certificates)" \
 --entitlements="/Users/me/Projects/Myapp/resources/mac/parent.plist" \
 --entitlements-inherit="/Users/me/Projects/Myapp/resources/mac/child.plist" \
 --provisioning-profile="/Users/me/Projects/Myapp/resources/mac/provisioning/Mac_Development.provisionprofile"

parent.plist

<?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.application-identifier</key>
    <string>my_team_id_from_distribution_certificates.com.electron.myapp</string>
    <key>com.apple.developer.team-identifier</key>
    <string>my_team_id_from_distribution_certificates</string>
    <key>com.apple.security.application-groups</key>
    <string>my_team_id_from_distribution_certificates.com.electron.myapp</string>
    <key>com.apple.security.app-sandbox</key>
    <true/>
    <key>com.apple.security.network.client</key>
    <true/>
  </dict>
</plist>

child.plist

<?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.app-sandbox</key>
    <true/>
    <key>com.apple.security.inherit</key>
    <true/>
  </dict>
</plist>

electron-osx-sign returned:

electron-osx-sign Signing application... +0ms
  electron-osx-sign > application         /Users/me/Projects/Myapp/out/Myapp-mas-x64/Myapp.app +3ms
  electron-osx-sign > platform            mas +1ms
  electron-osx-sign > entitlements        /Users/me/Projects/Myapp/resources/mac/parent.plist +0ms
  electron-osx-sign > child-entitlements  /Users/me/Projects/Myapp/resources/mac/child.plist +0ms
  electron-osx-sign > additional-binaries  +1ms
  electron-osx-sign > identity            Mac Developer: My_firstname My_lastname (my_dev_id) +0ms
  electron-osx-sign Signing... /Users/me/Projects/Myapp/out/Myapp-mas-x64/Myapp.app/Contents/Frameworks/Electron Framework.framework/Versions/A/Electron Framework +74ms
  electron-osx-sign Signing... /Users/me/Projects/Myapp/out/Myapp-mas-x64/Myapp.app/Contents/Frameworks/Electron Framework.framework/Versions/A/Libraries/libffmpeg.dylib +1s
  electron-osx-sign Signing... /Users/me/Projects/Myapp/out/Myapp-mas-x64/Myapp.app/Contents/Frameworks/Electron Framework.framework/Versions/A/Libraries/libnode.dylib +153ms
  electron-osx-sign Signing... /Users/me/Projects/Myapp/out/Myapp-mas-x64/Myapp.app/Contents/Frameworks/Electron Framework.framework +290ms
  electron-osx-sign Signing... /Users/me/Projects/Myapp/out/Myapp-mas-x64/Myapp.app/Contents/Frameworks/Myapp Helper EH.app/Contents/MacOS/Myapp Helper EH +1s
  electron-osx-sign Signing... /Users/me/Projects/Myapp/out/Myapp-mas-x64/Myapp.app/Contents/Frameworks/Myapp Helper EH.app +105ms
  electron-osx-sign Signing... /Users/me/Projects/Myapp/out/Myapp-mas-x64/Myapp.app/Contents/Frameworks/Myapp Helper NP.app/Contents/MacOS/Myapp Helper NP +111ms
  electron-osx-sign Signing... /Users/me/Projects/Myapp/out/Myapp-mas-x64/Myapp.app/Contents/Frameworks/Myapp Helper NP.app +115ms
  electron-osx-sign Signing... /Users/me/Projects/Myapp/out/Myapp-mas-x64/Myapp.app/Contents/Frameworks/Myapp Helper.app/Contents/MacOS/Myapp Helper +110ms
  electron-osx-sign Signing... /Users/me/Projects/Myapp/out/Myapp-mas-x64/Myapp.app/Contents/Frameworks/Myapp Helper.app +123ms
  electron-osx-sign Signing... /Users/me/Projects/Myapp/out/Myapp-mas-x64/Myapp.app/Contents/MacOS/Myapp +125ms
  electron-osx-sign Signing... /Users/me/Projects/Myapp/out/Myapp-mas-x64/Myapp.app +313ms
  electron-osx-sign Verifying sign... +302ms
  electron-osx-sign Verifying entitlements... +229ms
Application signed: /Users/me/Projects/Myapp/out/Myapp-mas-x64/Myapp.app

Any idea to solve this problem?

question extern

Most helpful comment

Hi @sethlu, thank you for your answer. After following your suggestions and a lot of tests, I always had the same problem. I checked all my source code to be sure and I finally found why:

I used app.makeSingleInstance(callback), the documentation says:

const {app} = require('electron')
let myWindow = null

const shouldQuit = app.makeSingleInstance((commandLine, workingDirectory) => {
  // Someone tried to run a second instance, we should focus our window.
  if (myWindow) {
    if (myWindow.isMinimized()) myWindow.restore()
    myWindow.focus()
  }
})

if (shouldQuit) {
  app.quit()
}

// Create myWindow, load the rest of the app, etc...
app.on('ready', () => {
})

The best way to be able to sign the app, is to do:

const {app} = require('electron')
let myWindow = null

function makeSingleInstance() {
  if (process.mas) return false // <= VERY IMPORTANT

  return app.makeSingleInstance((commandLine, workingDirectory) => {
    // Someone tried to run a second instance, we should focus our window.
    if (myWindow) {
      if (myWindow.isMinimized()) myWindow.restore()
      myWindow.focus()
    }
  })
}

const shouldQuit = makeSingleInstance()
if (shouldQuit) {
  return app.quit() // <= I read that "return" here is important too
}

// Create myWindow, load the rest of the app, etc...
app.on('ready', () => {
})

Now, I can sign my app and all work well :)

All 5 comments

Hi @kcampion, thanks for filing the issue! Right now I couldn't tell where the issue comes from without further info. Here are some of my immediate thoughts:

    <key>com.apple.application-identifier</key>
    <string>my_team_id_from_distribution_certificates.com.electron.myapp</string>
    <key>com.apple.developer.team-identifier</key>
    <string>my_team_id_from_distribution_certificates</string>
    <key>com.apple.security.application-groups</key>
    <string>my_team_id_from_distribution_certificates.com.electron.myapp</string>

With the team id being correct, I think the com.electron.myapp part should match what is restricted by the provisioning profile (being wildcard or specific to the app) and not com.electron.myapp since your team/company probably has a different reversed network domain.

Also, electron-osx-sign should be able to detect those settings from the provisioning profile you input, and it's quite safe to just ignore those few lines in the entitlements file. (The child entitlements file may be safely ignored since it's the same by default signing.)


If you would to sign your app again with export DEBUG=electron-osx-sign* (rather than export DEBUG=electron-osx-sign--there should be a more comprehensive log of everything electron-osx-sign outputs--I can help you from there further.

Hi @sethlu, thank you for your answer. After following your suggestions and a lot of tests, I always had the same problem. I checked all my source code to be sure and I finally found why:

I used app.makeSingleInstance(callback), the documentation says:

const {app} = require('electron')
let myWindow = null

const shouldQuit = app.makeSingleInstance((commandLine, workingDirectory) => {
  // Someone tried to run a second instance, we should focus our window.
  if (myWindow) {
    if (myWindow.isMinimized()) myWindow.restore()
    myWindow.focus()
  }
})

if (shouldQuit) {
  app.quit()
}

// Create myWindow, load the rest of the app, etc...
app.on('ready', () => {
})

The best way to be able to sign the app, is to do:

const {app} = require('electron')
let myWindow = null

function makeSingleInstance() {
  if (process.mas) return false // <= VERY IMPORTANT

  return app.makeSingleInstance((commandLine, workingDirectory) => {
    // Someone tried to run a second instance, we should focus our window.
    if (myWindow) {
      if (myWindow.isMinimized()) myWindow.restore()
      myWindow.focus()
    }
  })
}

const shouldQuit = makeSingleInstance()
if (shouldQuit) {
  return app.quit() // <= I read that "return" here is important too
}

// Create myWindow, load the rest of the app, etc...
app.on('ready', () => {
})

Now, I can sign my app and all work well :)

@kcampion glad that works! & thanks for reminding me of some old discussions about makeSingleInstance():

Wait, you fixed a network permission issue from app-sandbox by not creating Electron window instances? Were you even using tcp server? It seems to me that those are not related.

I also ran into this for my local development mas build. I was using "requestSingleInstanceLock" though.

Adding the check for process.mas fixed the issue

if (!process.mas){
  const gotLock = app.requestSingleInstanceLock();
  if (!gotLock) {
    return app.quit();
  }
}

I also had the following in the parent entitlement instead of just com.apple.security.network.client

    <key>com.apple.security.network.client</key>
    <true/>
    <key>com.apple.security.network.server</key>
    <true/>
Was this page helpful?
0 / 5 - 0 ratings