Invalid Code Signature Error on Electron App After Signing with Hardened Runtime

Hi All,

I've been running into issues with codesigning my Electron application with hardened runtime. The application verifies as being properly codesigned using codesign verify, passes notarization and is stapled properly, passes gatekeeper checks using spctl, and also passes Apple's check-signature tool.



The application itself isn't built with xcode but rather by using Electron's prebuilt binaries and then moving our javascript, css, and other non-code resources into the respective folder (.app/Content/Resources/app). I codesign via commandline using xcode 10.1 on Mac OS X 10.14.1.



I've tried reducing the application down to the bare Electron startup, but it still fails.



Looking at the otool -l result on the binary, I have a suspicion that it's due to the Electron binary trying to reach out of the application package to load some libraries, but I'm not sure how to confirm. I've attached the relevant information/log outputs below, any help would be greatly appreciated!


Redacted Crash Report Snippet:


Process:               Electron [44923]
Path:                  /Applications/****.app/Contents/MacOS/Electron
Identifier:            com.****.client.mac
Version:               5.0.7 (5.0.7)
Code Type:             X86-64 (Native)
Parent Process:        ??? [1]
Responsible:           Electron [44923]
User ID:               533436293
Date/Time:             2019-08-14 11:03:24.712 -0700
OS Version:            Mac OS X 10.14.6 (18G87)
Report Version:        12
Anonymous UUID:        DA9050BD-26FD-A720-9753-315E0D3D6F4C
Sleep/Wake UUID:       99B984C9-1273-4AC4-AD5B-83ABEAC6B60F
Time Awake Since Boot: 34000 seconds
Time Since Wake:       1200 seconds
System Integrity Protection: enabled
Crashed Thread:        0  Dispatch queue: com.apple.main-thread
Exception Type:        EXC_BAD_ACCESS (Code Signature Invalid)
Exception Codes:       0x0000000000000032, 0x00003655e4d82040
Exception Note:        EXC_CORPSE_NOTIFY
Termination Reason:    Namespace CODESIGNING, Code 0x2
kernel messages:
VM Regions Near 0x3655e4d82040:
    Memory Tag 255         00003655e4d81000-00003655e4d82000 [    4K] ---/rwx SM=NUL 
--> Memory Tag 255         00003655e4d82000-00003655e4dff000 [  500K] r-x/rwx SM=COW 
    Memory Tag 255         00003655e4dff000-00003655ecce9000 [126.9M] ---/rwx SM=NUL 
Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
0   ???                             0x00003655e4d82040 0 + 59742539489344
1   com.github.Electron.framework   0x0000000109eebc88 v8::internal::RegExpImpl::IrregexpExecRaw(v8::internal::Isolate*, v8::internal::Handle, v8::internal::Handle, int, int*, int) + 376 (jsregexp.cc:457)
2   com.github.Electron.framework   0x0000000109eea87e v8::internal::RegExpImpl::IrregexpExec(v8::internal::Isolate*, v8::internal::Handle, v8::internal::Handle, int, v8::internal::Handle) + 334 (jsregexp.cc:547)
3   com.github.Electron.framework   0x0000000109f80a6d v8::internal::Runtime_RegExpExec(int, unsigned long*, v8::internal::Isolate*) + 301 (runtime-regexp.cc:914)
4   com.github.Electron.framework   0x000000010a2c218b Builtins_CEntry_Return1_DontSaveFPRegs_ArgvOnStack_NoBuiltinExit + 75
5   com.github.Electron.framework   0x000000010a289080 Builtins_RegExpPrototypeTest + 1472
6   com.github.Electron.framework   0x000000010a222237 Builtins_InterpreterEntryTrampoline + 695
7   com.github.Electron.framework   0x000000010a222237 Builtins_InterpreterEntryTrampoline + 695
8   com.github.Electron.framework   0x000000010a222237 Builtins_InterpreterEntryTrampoline + 695
9   com.github.Electron.framework   0x000000010a222237 Builtins_InterpreterEntryTrampoline + 695
10  com.github.Electron.framework   0x000000010a222237 Builtins_InterpreterEntryTrampoline + 695
11  com.github.Electron.framework   0x000000010a222237 Builtins_InterpreterEntryTrampoline + 695
12  com.github.Electron.framework   0x000000010a222237 Builtins_InterpreterEntryTrampoline + 695
13  com.github.Electron.framework   0x000000010a222237 Builtins_InterpreterEntryTrampoline + 695
14  com.github.Electron.framework   0x000000010a222237 Builtins_InterpreterEntryTrampoline + 695
15  com.github.Electron.framework   0x000000010a21fae0 Builtins_JSEntryTrampoline + 96
16  com.github.Electron.framework   0x000000010a21f86d Builtins_JSEntry + 141
17  com.github.Electron.framework   0x0000000109d2c9cb v8::internal::(anonymous namespace)::Invoke(v8::internal::Isolate*, v8::internal::(anonymous namespace)::InvokeParams const&) + 683
18  com.github.Electron.framework   0x0000000109d2c70b v8::internal::Execution::Call(v8::internal::Isolate*, v8::internal::Handle, v8::internal::Handle, int, v8::internal::Handle*) + 203 (execution.cc:358)
19  com.github.Electron.framework   0x0000000109897aeb v8::Function::Call(v8::Local, v8::Local, int, v8::Local*) + 459 (api.cc:5029)
20  com.github.Electron.framework   0x000000010a8742fb (anonymous namespace)::InitAsarSupport(v8::Isolate*, v8::Local) + 171 (atom_api_asar.cc:129)
21  com.github.Electron.framework   0x000000010a87555d mate::internal::Dispatcher)>::DispatchToCallback(v8::FunctionCallbackInfo const&) + 269 (function_template.h:239)
22  com.github.Electron.framework   0x0000000109a3fbaf v8::internal::FunctionCallbackArguments::Call(v8::internal::CallHandlerInfo) + 655 (api-arguments-inl.h:147)
23  com.github.Electron.framework   0x00000001099fe00e v8::internal::MaybeHandle v8::internal::(anonymous namespace)::HandleApiCallHelper(v8::internal::Isolate*, v8::internal::Handle, v8::internal::Handle, v8::internal::Handle, v8::internal::Handle, v8::internal::BuiltinArguments) + 670 (builtins-api.cc:111)
24  com.github.Electron.framework   0x00000001099fd48a v8::internal::Builtin_Impl_HandleApiCall(v8::internal::BuiltinArguments, v8::internal::Isolate*) + 250
25  com.github.Electron.framework   0x000000010a2c218b Builtins_CEntry_Return1_DontSaveFPRegs_ArgvOnStack_NoBuiltinExit + 75
26  com.github.Electron.framework   0x000000010a222237 Builtins_InterpreterEntryTrampoline + 695
27  com.github.Electron.framework   0x000000010a222237 Builtins_InterpreterEntryTrampoline + 695
28  com.github.Electron.framework   0x000000010a222237 Builtins_InterpreterEntryTrampoline + 695
29  com.github.Electron.framework   0x000000010a21fae0 Builtins_JSEntryTrampoline + 96
30  com.github.Electron.framework   0x000000010a21f86d Builtins_JSEntry + 141
31  com.github.Electron.framework   0x0000000109d2c9cb v8::internal::(anonymous namespace)::Invoke(v8::internal::Isolate*, v8::internal::(anonymous namespace)::InvokeParams const&) + 683
32  com.github.Electron.framework   0x0000000109d2c70b v8::internal::Execution::Call(v8::internal::Isolate*, v8::internal::Handle, v8::internal::Handle, int, v8::internal::Handle*) + 203 (execution.cc:358)
33  com.github.Electron.framework   0x0000000109897aeb v8::Function::Call(v8::Local, v8::Local, int, v8::Local*) + 459 (api.cc:5029)
34  com.github.Electron.framework   0x000000010db3bea4 node::ExecuteBootstrapper(node::Environment*, char const*, std::__1::vector<v8::local, std::__1::allocator<v8::local > >*, std::__1::vector<v8::local, std::__1::allocator<v8::local > >*) + 116 (node.cc:233)
35  com.github.Electron.framework   0x000000010db3c0d4 node::StartExecution(node::Environment*, char const*) + 356
36  com.github.Electron.framework   0x000000010a8a0928 atom::NodeBindings::LoadEnvironment(node::Environment*) + 24 (node_bindings.cc:359)
37  com.github.Electron.framework   0x000000010a813505 atom::AtomBrowserMainParts::PostEarlyInitialization() + 293 (atom_browser_main_parts.cc:331)
38  com.github.Electron.framework   0x0000000109180cb0 content::BrowserMainLoop::EarlyInitialization() + 224 (browser_main_loop.cc:670)
39  com.github.Electron.framework   0x00000001091854c0 content::BrowserMainRunnerImpl::Initialize(content::MainFunctionParams const&) + 928 (browser_main_runner_impl.cc:123)
40  com.github.Electron.framework   0x0000000109180474 content::BrowserMain(content::MainFunctionParams const&) + 244 (browser_main.cc:43)
41  com.github.Electron.framework   0x000000010a544b5e content::ContentMainRunnerImpl::RunServiceManager(content::MainFunctionParams&, bool) + 862 (content_main_runner_impl.cc:954)
42  com.github.Electron.framework   0x000000010a5447d1 content::ContentMainRunnerImpl::Run(bool) + 273
43  com.github.Electron.framework   0x000000010c0efa6f service_manager::Main(service_manager::MainParams const&) + 2799 (main.cc:461)
44  com.github.Electron.framework   0x000000010a543c24 content::ContentMain(content::ContentMainParams const&) + 68 (content_main.cc:19)
45  com.github.Electron.framework   0x000000010862ba94 AtomMain + 84
46  com.****.client.mac             0x0000000105c7e9b0 0x105c7d000 + 6576
47  libdyld.dylib                   0x00007fff6931f3d5 start + 1


system.log output:


**** com.apple.xpc.launchd[1] (com.apple.xpc.launchd.oneshot.0x10000043.Electron[44923]): Binary is improperly signed.


check-signature output:


****:Applications ****$ ./check-signature ****.app/
(c) 2014 Apple Inc.  All rights reserved.
YES


codesign -dv -vvvv --entitlements output:

****:Applications ****$ codesign -dv -vvvv ****.app/
Executable=/Applications/****.app/Contents/MacOS/Electron
Identifier=com.****.client.mac
Format=app bundle with Mach-O thin (x86_64)
CodeDirectory v=20500 size=1759 flags=0x10000(runtime) hashes=46+5 location=embedded
VersionPlatform=1
VersionMin=657920
VersionSDK=658432
Hash type=sha256 size=32
CandidateCDHash sha1=9585c58e11bab20a5e2139f972490ffee8a6510e
CandidateCDHash sha256=1b6ca3c24c4cd75d4e7668f6096f9ec5a47234d2
Hash choices=sha1,sha256
Page size=4096
    -5=ce4fdab5dc8d66c03643f7ceee232b18de8cf597e5f8b869daf92cd26b167964
    -4=0000000000000000000000000000000000000000000000000000000000000000
    -3=16c136379d06a0aec6418c845743443ded97c3da56165d9fce49844ae3e149d9
    -2=ca0588d22346861b54a340e51d2073a74c4c4a6f0288c0618d062637d81b84e7
CDHash=1b6ca3c24c4cd75d4e7668f6096f9ec5a47234d2
Signature size=8989
Authority=Developer ID Application: **** (****)
Authority=Developer ID Certification Authority
Authority=Apple Root CA
Timestamp=Aug 12, 2019 16:02:16
Info.plist entries=22
TeamIdentifier=****
Runtime Version=10.12.0
Sealed Resources version=2 rules=13 files=710
Internal requirements count=1 size=180
<?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.cs.disable-library-validation</key>
        <true/>
    </dict>
</plist>


spctl --assess output:

****:Applications ****$ spctl --assess --type execute --verbose --ignore-cache --no-cache ****.app/
****.app/: accepted
source=Developer ID



otool -l snippet on executable:


Load command 7
          cmd LC_LOAD_DYLINKER
      cmdsize 32
         name /usr/lib/dyld (offset 12)
Load command 8
     cmd LC_UUID
cmdsize 24
    uuid 3788637B-0A53-3737-B3B6-C827ABF3E314
Load command 9
      cmd LC_VERSION_MIN_MACOSX
  cmdsize 16
  version 10.10
      sdk 10.12
Load command 10
      cmd LC_SOURCE_VERSION
  cmdsize 16
  version 0.0
Load command 11
       cmd LC_MAIN
   cmdsize 24
  entryoff 6336
stacksize 0
Load command 12
          cmd LC_LOAD_DYLIB
      cmdsize 88
         name /System/Library/Frameworks/Cocoa.framework/Versions/A/Cocoa (offset 24)
   time stamp 2 Wed Dec 31 16:00:02 1969
      current version 22.0.0
compatibility version 1.0.0
Load command 13
          cmd LC_LOAD_DYLIB
      cmdsize 96
         name /System/Library/Frameworks/Foundation.framework/Versions/C/Foundation (offset 24)
   time stamp 2 Wed Dec 31 16:00:02 1969
      current version 1349.63.0
compatibility version 300.0.0
Load command 14
          cmd LC_LOAD_DYLIB
      cmdsize 88
         name /System/Library/Frameworks/IOKit.framework/Versions/A/IOKit (offset 24)
   time stamp 2 Wed Dec 31 16:00:02 1969
      current version 275.0.0
compatibility version 1.0.0
Load command 15
          cmd LC_LOAD_DYLIB
      cmdsize 96
         name /System/Library/Frameworks/Security.framework/Versions/A/Security (offset 24)
   time stamp 2 Wed Dec 31 16:00:02 1969
      current version 57740.51.2
compatibility version 1.0.0
Load command 16
          cmd LC_LOAD_DYLIB
      cmdsize 112
         name /System/Library/Frameworks/SystemConfiguration.framework/Versions/A/SystemConfiguration (offset 24)
   time stamp 2 Wed Dec 31 16:00:02 1969
      current version 888.51.1
compatibility version 1.0.0
Load command 17
          cmd LC_LOAD_DYLIB
      cmdsize 80
         name @rpath/Electron Framework.framework/Electron Framework (offset 24)
   time stamp 2 Wed Dec 31 16:00:02 1969
      current version 0.0.0
compatibility version 0.0.0
Load command 18
          cmd LC_LOAD_DYLIB
      cmdsize 56
         name /usr/lib/libSystem.B.dylib (offset 24)
   time stamp 2 Wed Dec 31 16:00:02 1969
      current version 1238.50.2
compatibility version 1.0.0
Load command 19
          cmd LC_RPATH
      cmdsize 48
         path @executable_path/../Frameworks (offset 12)
Load command 20
      cmd LC_FUNCTION_STARTS
  cmdsize 16
  dataoff 182176
datasize 752
Load command 21
      cmd LC_DATA_IN_CODE
  cmdsize 16
  dataoff 182928
datasize 56
Load command 22
      cmd LC_CODE_SIGNATURE
  cmdsize 16
  dataoff 186048
datasize 21696

Replies

The problem here is that notarisation requires the hardened runtime and the hardened runtime, by default, prevents apps from generating code on the fly. The backtrace here strongly suggests that your app is crashing because the V8 JavaScript engine is doing just that.

The best way to resolve such issues depends on the exact behaviour of the third-party tools in question. For more background on this, see this thread.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Thanks Quinn,


I used that thread as a reference for debugging my issue prior to posting on the forums. I crafted an entitlements file with both the jit and unsigned executable memory allowment and signed the app and files with it. I can see that it's attached when I run a codesign --verify on the app, but is there any other way to check if it is actually working?

As a followup, I have also built an Electron app from the ground up using their prebuilt binaries and then dropping in their Hello World app (https://electronjs.org/docs/tutorial/first-app) verbatim into the right folder. This also passes every codesign verification as well as gatekeeper and notarization checks however it fials with the exact same error despite being passed in the following entitlements:

<?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/>
  </dict>
</plist>

I’m sorry but I’ve reached the limits of the help I can provide you. DTS’s role here at Apple is to support Apple’s APIs and tools. We do not support third-party tools. If you have questions about how to use such tools, you must escalate those with your tool’s vendor.

If your tools vendor has questions about how their tool interacts with the hardened runtime, I’m happy to help them. They can post here if they want, but it’d probably be better to open a DTS tech support incident. Keep in mind, however, that DTS will only accept such questions if they come from the tools vendor [1].

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

[1] In the case of an open source project, this translates to someone who is familiar with the code and can make changes to it.

Hi Quinn,
Could you please look onto the below issue, I am struggling to get it resolved for a very long time.
https://forums.developer.apple.com/message/387691

If I don't sign or notarize the application, everything works fine; the crash occurs when starting a certain process in hardened runtime (after signing and notarization), It shows signal killed.