App Extension Network Extension - failed to start, signature check failed

Howdy,

I've been developing a packet tunnel extension meant to run on iOS and MacOS. For development I'm using xcodegen + xcodebuild to assemble a bunch of swift and rust code together.

I'm moving from direct TUN device management on Mac to shipping a Network Extension (appex). With that move I noticed that on some mac laptops NE fails to start completely, whilst on others everything works fine.

I'm using CODE_SIGN_STYLE: Automatic, Apple IDs are within the same team, all devices are registered as dev devices. Signing dev certificates, managed by xcode.

Some suspicious logs:

(NetworkExtension) [com.apple.networkextension:] Signature check failed: code failed to satisfy specified code requirement(s)
...
(NetworkExtension) [com.apple.networkextension:] Provider is not signed with a Developer ID certificate

What could be the issue? Where those inconsistencies across devices might come from?

Answered by deteam444 in 864815022

Looking into the sysex vs appex, thanks. We probably want to support both eventually, but at the moment the app is distributed on our own with Developer ID signing + notarizing.

Also, somehow the issue in the post was cause by a previously installed (6 months ago or more) iOS version of the very same app (same identifier for the app and NE). TestFlight iOS app was also somewhere in /Applications and probably affected developer build of the mac version.

After deleting the iOS TestFlight version of the app we managed to finally run in Debug mode on the failing device.

App is not sandboxed, NE is sandboxed. Network extension entitlements (packet-tunnel) are specified for both targets.

The first thing to rule out is the device not actually being included in the profile. Do this:

  1. Dump the profile of the app:

    % security cms -D -i MyApp.app/Contents/embedded.provisionprofile 
    
  2. Dump the profile of the provider:

    % security cms -D -i MyApp.app/Contents/PlugIns/MyAppEx.appex/Contents/embedded.provisionprofile
    
  3. Check that the ProvisionedDevices lists match.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Failing device is mentioned in provisioning profiles for both app and appex (matching Provisioning UDID).

This log also appears on another device where everything's fine, not sure if it's relevant or what to make of it:

(NetworkExtension) [com.apple.networkextension:] Provider is not signed with a Developer ID certificate

For now assuming it's just noise and the true issue is in signature/smth else validation.

Noticed an interesting thing: if I try to run .app built and signed on the failing device after allowing it via security settings ("Open Anyway") and removing quarantine, then NE gets registered and also started successfully.

I also compared entitlements, signatures and provisioning profiles for both app and appex. They all seem to match for .app bundles done on both devices.

Hmmm. You are somewhat crossing the streams here. Development-signed builds are intended for development machines, and there’s an implicit assumption that apps built on development won’t be quarantined.

Normally I’d suggest you get around that by following the Developer ID path — signing with Developer ID and then notarisation — but that’s not really feasible for an NE appex, because we don’t support those for Developer ID. Directly distributed apps have to use a sysex. And converting an appex to a sysex is not a trivial task.

Except…

Are you ultimately planning to ship this app on the Mac App Store? If not, you might as well grasp the sysex nettle now.

For detailed info about NE distribution limitations, see TN3134 Network Extension provider deployment.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Looking into the sysex vs appex, thanks. We probably want to support both eventually, but at the moment the app is distributed on our own with Developer ID signing + notarizing.

Also, somehow the issue in the post was cause by a previously installed (6 months ago or more) iOS version of the very same app (same identifier for the app and NE). TestFlight iOS app was also somewhere in /Applications and probably affected developer build of the mac version.

After deleting the iOS TestFlight version of the app we managed to finally run in Debug mode on the failing device.

issue … was cause by a previously installed … iOS version of the very same app

Oh, wow. That makes sense [1], but it’s not something I would’ve thought of. Thanks for the titbit.

at the moment the app is distributed on our own with Developer ID signing + notarizing.

OK. In that case you need to get on to the sysex train, because we only support appex packaging in Mac App Store apps. Again, TN3134 is a key reference here.

I really need to write up a doc that explains… oh wait, Past Quinn™ has done as a solid here! See Network Extension Provider Packaging.

Finally, watch out for the pitfall described in Exporting a Developer ID Network Extension.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

[1] TN3134 explains how macOS is able to use NE tunnel provider from iOS Apps on Mac, and it’s easy to see how that could cause problems if you then tried to start a native version.

Sysex train it is. Few follow-up questions:

  1. Is it really necessary to disable SIP in order to be able to conveniently test system extensions signed with Apple Development cert and automatic code signing?
  2. Entitlement names for Release build vs Debug would differ if we're planning to re-sign Release build with Developer ID, right?

It seems that for local development appex might be better, if practically there's almost no difference besides tweaks in entitlements/xcodegen configuration, main function and sysex activation code.

While trying to get sysx working locally with SIP disabled, I ended up with the following error message:

System extension activation failed: Invalid extension configuration in Info.plist and/or entitlements: System extension <SYSX_BUNDLE_ID>.systemextension does not appear to belong to any extension categories

Entitlements and overall configuration seem in order. What could that be?

Is it really necessary to disable SIP …

Not for NE sysexen. See Debugging a Network Extension Provider.

Entitlement names for Release build vs Debug would differ if we're planning to re-sign Release build with Developer ID

Probably not. In Xcode, I recommend that you use automatic code signing for both your Debug and Release build configurations. Things are just easier that way.

When you choose Product > Archive to generate an Xcode archive, that’ll be a Release build with Apple Developer signing. The Xcode organiser then re-signs when you export that archive. That works for all situations except Developer ID. Xcode has not yet been educated to about the -systemextension edge case. So, you have to fix the entitlements when you export from your archive.

I ended up with the following error message

Note the extension categories in that message. There are various categories of sysex, including an NE provider, an Endpoint Security client, and a DriverKit driver. It seems that the system hasn’t be able to determine the category of your sysex. This is usually because of an Info.plist problem.

My experience is that, if you create a test project using Xcode and add an NE sysex target to it, Xcode will set up the Info.plist correctly and you can crib from there.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

App Extension Network Extension - failed to start, signature check failed
 
 
Q