System Extension app-group entitlement issue

I am trying to run a Network System Extension (Packet Tunnel) that is successfully running as MAS Network Extension, but I'm facing a problem that neither app nor sysex gets app-group entitlement. Probably because of that my sysex can't find keychain items saved by the app.

taskgated-helper  ConfigurationProfiles  Unsatisfied entitlements: com.apple.security.application-groups


I have app-groups configured in xcode for both targets, but provisioning profiles doesn't include them even though I have them selected on app ID's.


I'm also getting a bunch of Security errors and NetworkExtension for some reason reports "Signature check failed: invalid signature (code or signature have been modified)"

default 17:34:48.935971+0300 sysextd sysextd Extension point confirmed that extension com.company.appAbc.PacketTunnel-OpenVPN is runnable.
default 17:34:58.929349+0300 AppAbc Security Adding securityd connection to pool, total now 3
default 17:35:06.957159+0300 AppAbc NetworkExtension Saving configuration AppAbc with existing signature (null)
default 17:35:07.168468+0300 AppAbc NetworkExtension Successfully saved configuration AppAbc
default 17:35:07.192204+0300 AppAbc NetworkExtension Received a com.apple.neconfigurationchanged notification with token 38
default 17:35:07.308162+0300 AppAbc NetworkExtension Saving configuration AppAbc with existing signature {length = 20, bytes = 0xa032bdd71140be2af6788e2dc77930a115c17b25}
default 17:35:07.329977+0300 AppAbc NetworkExtension Received a com.apple.neconfigurationchanged notification with token 38
default 17:35:07.330511+0300 AppAbc NetworkExtension Successfully saved configuration AppAbc
default 17:35:07.336086+0300 AppAbc NetworkExtension Saving configuration AppAbc with existing signature {length = 20, bytes = 0x45e64b4ed5b0a1ad6061e3ba5cc05dddd003cd52}
default 17:35:07.382735+0300 AppAbc NetworkExtension Received a com.apple.neconfigurationchanged notification with token 38
default 17:35:07.383265+0300 AppAbc NetworkExtension Successfully saved configuration AppAbc
default 17:35:07.518667+0300 taskgated-helper ConfigurationProfiles allowing entitlement(s) for com.company.appAbc.PacketTunnel-OpenVPN due to provisioning profile (isUPP: 1)
error 17:35:07.526352+0300 taskgated-helper ConfigurationProfiles com.company.appAbc.PacketTunnel-OpenVPN: Unsatisfied entitlements: com.apple.security.application-groups
error 17:35:07.526380+0300 taskgated-helper ConfigurationProfiles Disallowing: com.company.appAbc.PacketTunnel-OpenVPN
default 17:35:08.781878+0300 secinitd secinitd com.company.appAbc.PacketTunnel-OpenVPN[95856]: root path for bundle "" of main executable ""
default 17:35:09.165083+0300 secinitd secinitd com.company.appAbc.PacketTunnel-OpenVPN[95856]: AppSandbox request successful
default 17:35:09.240267+0300 com.company.appAbc.PacketTunnel-OpenVPN Security MacOS error: -25337
default 17:35:09.251136+0300 com.company.appAbc.PacketTunnel-OpenVPN Security CSSM Exception: 3 unknown error 3=3
default 17:35:09.253611+0300 com.company.appAbc.PacketTunnel-OpenVPN Security CSSM Exception: -2147414013 CSSMERR_DL_MDS_ERROR
default 17:35:09.255763+0300 com.company.appAbc.PacketTunnel-OpenVPN Security CSSM Exception: -2147414013 CSSMERR_DL_MDS_ERROR
default 17:35:09.259015+0300 com.company.appAbc.PacketTunnel-OpenVPN Security MacOS error: -25337
default 17:35:09.263010+0300 com.company.appAbc.PacketTunnel-OpenVPN Security CSSM Exception: 3 unknown error 3=3
default 17:35:09.267611+0300 com.company.appAbc.PacketTunnel-OpenVPN Security CSSM Exception: -2147414013 CSSMERR_DL_MDS_ERROR
default 17:35:09.270637+0300 com.company.appAbc.PacketTunnel-OpenVPN Security CSSM Exception: -2147414013 CSSMERR_DL_MDS_ERROR
default 17:35:09.273530+0300 com.company.appAbc.PacketTunnel-OpenVPN Security MacOS error: -25337
default 17:35:09.277920+0300 com.company.appAbc.PacketTunnel-OpenVPN Security CSSM Exception: 3 unknown error 3=3
default 17:35:09.283042+0300 com.company.appAbc.PacketTunnel-OpenVPN Security CSSM Exception: -2147414013 CSSMERR_DL_MDS_ERROR
default 17:35:09.291778+0300 com.company.appAbc.PacketTunnel-OpenVPN Security CSSM Exception: -2147414013 CSSMERR_DL_MDS_ERROR
default 17:35:09.296948+0300 com.company.appAbc.PacketTunnel-OpenVPN Security Adding securityd connection to pool, total now 1
default 17:35:09.296956+0300 com.company.appAbc.PacketTunnel-OpenVPN Security got event: Connection invalid
default 17:35:09.297116+0300 com.company.appAbc.PacketTunnel-OpenVPN Security Failed to talk to secd after 4 attempts.
default 17:35:09.297573+0300 com.company.appAbc.PacketTunnel-OpenVPN Security using system preferences
default 17:35:09.299722+0300 com.company.appAbc.PacketTunnel-OpenVPN Security MacOS error: -25337
default 17:35:09.303518+0300 com.company.appAbc.PacketTunnel-OpenVPN Security CSSM Exception: 3 unknown error 3=3
default 17:35:09.305860+0300 com.company.appAbc.PacketTunnel-OpenVPN Security CSSM Exception: -2147414013 CSSMERR_DL_MDS_ERROR
default 17:35:09.308235+0300 com.company.appAbc.PacketTunnel-OpenVPN Security MacOS error: -25337
default 17:35:09.310523+0300 com.company.appAbc.PacketTunnel-OpenVPN Security CSSM Exception: 3 unknown error 3=3
default 17:35:09.314336+0300 com.company.appAbc.PacketTunnel-OpenVPN Security CSSM Exception: -2147414013 CSSMERR_DL_MDS_ERROR
default 17:35:09.318363+0300 com.company.appAbc.PacketTunnel-OpenVPN Security CSSM Exception: -2147414013 CSSMERR_DL_MDS_ERROR
default 17:35:09.320930+0300 com.company.appAbc.PacketTunnel-OpenVPN Security MacOS error: -25337
default 17:35:09.323378+0300 com.company.appAbc.PacketTunnel-OpenVPN Security CSSM Exception: 3 unknown error 3=3
default 17:35:09.325901+0300 com.company.appAbc.PacketTunnel-OpenVPN Security CSSM Exception: -2147414013 CSSMERR_DL_MDS_ERROR
default 17:35:09.328656+0300 com.company.appAbc.PacketTunnel-OpenVPN Security CSSM Exception: -2147414013 CSSMERR_DL_MDS_ERROR
default 17:35:09.332580+0300 com.company.appAbc.PacketTunnel-OpenVPN Security MacOS error: -25337
default 17:35:09.346565+0300 com.company.appAbc.PacketTunnel-OpenVPN Security CSSM Exception: 3 unknown error 3=3
default 17:35:09.352010+0300 com.company.appAbc.PacketTunnel-OpenVPN Security CSSM Exception: -2147414013 CSSMERR_DL_MDS_ERROR
default 17:35:09.354244+0300 com.company.appAbc.PacketTunnel-OpenVPN Security CSSM Exception: -2147414013 CSSMERR_DL_MDS_ERROR
default 17:35:09.356355+0300 com.company.appAbc.PacketTunnel-OpenVPN Security Failed to talk to secd after 4 attempts.
default 17:35:09.356903+0300 com.company.appAbc.PacketTunnel-OpenVPN Security MacOS error: -25337
default 17:35:09.360582+0300 com.company.appAbc.PacketTunnel-OpenVPN Security CSSM Exception: 3 unknown error 3=3
default 17:35:09.364850+0300 com.company.appAbc.PacketTunnel-OpenVPN Security CSSM Exception: -2147414013 CSSMERR_DL_MDS_ERROR
default 17:35:09.368221+0300 com.company.appAbc.PacketTunnel-OpenVPN Security CMSDecoderCopySignerStatus failed with kCMSSignerInvalidSignature error (3)
default 17:35:09.368253+0300 com.company.appAbc.PacketTunnel-OpenVPN Security MacOS error: -67061
default 17:35:09.369765+0300 com.company.appAbc.PacketTunnel-OpenVPN NetworkExtension Signature check failed: invalid signature (code or signature have been modified)
default 17:35:09.533751+0300 com.company.appAbc.PacketTunnel-OpenVPN NetworkExtension [Extension com.company.appAbc]: Calling startTunnelWithOptions with options 0x7fb447a0c640
default 17:35:09.636368+0300 kernel Sandbox Sandbox: 7 duplicate reports for com.company.appA deny(1) file-write-data /private/var/db/mds/system/mds.lock
default 17:35:13.275423+0300 com.company.appAbc.PacketTunnel-OpenVPN NetworkExtension [Extension com.company.appAbc]: provider set tunnel configuration to (null)
default 17:35:13.298472+0300 com.company.appAbc.PacketTunnel-OpenVPN NetworkExtension [Extension com.company.appAbc]: provider set tunnel configuration to
  { ... }
default 17:35:13.760461+0300 com.company.appAbc.PacketTunnel-OpenVPN CoreFoundation Attempting to add source to main runloop, but the main thread has exited. This message will only log once. Break on _CFRunLoopError_MainThreadHasExited to debug.
default 17:35:14.230487+0300 com.company.appAbc.PacketTunnel-OpenVPN Security MacOS error: -25337
default 17:35:14.236639+0300 com.company.appAbc.PacketTunnel-OpenVPN Security CSSM Exception: 3 unknown error 3=3
default 17:35:14.244544+0300 com.company.appAbc.PacketTunnel-OpenVPN Security CSSM Exception: -2147414013 CSSMERR_DL_MDS_ERROR
default 17:35:14.249541+0300 com.company.appAbc.PacketTunnel-OpenVPN Security CSSM Exception: -2147414013 CSSMERR_DL_MDS_ERROR
default 17:35:14.300451+0300 com.company.appAbc.PacketTunnel-OpenVPN NetworkExtension [Extension com.company.appAbc]: provider set tunnel configuration to (null)
error 17:35:14.315789+0300 com.company.appAbc.PacketTunnel-OpenVPN CocoaLumberjack [Error] [openvpn-adapter.connection] [AAOpenVPNPacketTunnelProvider.swift:304] openVPNAdapter(_:handleError:) > [OVPN] Did recieve fatal error:
  Error Domain=me.ss-abramchuk.openvpn-adapter.error-domain Code=70 "Failed to establish connection with OpenVPN server" UserInfo={NSLocalizedDescription=Failed to establish connection with OpenVPN server, me.ss-abramchuk.openvpn-adapter.error-key.message=ClientState::attach() can only be called once per ClientState instantiation, me.ss-abramchuk.openvpn-adapter.error-key.fatal=true, NSLocalizedFailureReason=Unknown error.}
error 17:35:14.326776+0300 com.company.appAbc.PacketTunnel-OpenVPN CocoaLumberjack [Error] [openvpn-adapter.connection] [AAPacketTunnelProvider.swift:68] cancelTunnelWithError(_:) > Canceling tunnel due to the error:
  Error Domain=me.ss-abramchuk.openvpn-adapter.error-domain Code=70 "Failed to establish connection with OpenVPN server" UserInfo={NSLocalizedDescription=Failed to establish connection with OpenVPN server, me.ss-abramchuk.openvpn-adapter.error-key.message=ClientState::attach() can only be called once per ClientState instantiation, me.ss-abramchuk.openvpn-adapter.error-key.fatal=true, NSLocalizedFailureReason=Unknown error.}
default 17:35:14.351120+0300 com.company.appAbc.PacketTunnel-OpenVPN NetworkExtension [Extension com.company.appAbc]: IPC detached
default 17:35:14.357134+0300 AppAbc NetworkExtension Last disconnect error for AppAbc changed from "none" to "Failed to establish connection with OpenVPN server"

Accepted Reply

The App Groups mechanism works differently on macOS and iOS. Let me start by explaining that difference, after which I’ll come back to your specific issues.

IMPORTANT In this context I’m using macOS to refer to a native macOS app. In Mac Catalyst things behave as they do on iOS. Likewise for iOS Apps on Mac.

On iOS, App Groups must be allowlisted by your provisioning profile. The exact opposite is true on macOS, where there’s no way to allowlist your App Group with a profile.

Consider this iOS app:

% codesign -d --entitlements :- iOSTest.app
…
<dict>
  <key>application-identifier</key>
  <string>SKMME9E2Y8.com.example.apple-samplecode.iOSTest</string>
  <key>com.apple.developer.team-identifier</key>
  <string>SKMME9E2Y8</string>
  <key>com.apple.security.application-groups</key>
  <array>
    <string>group.com.example.apple-samplecode.iOSTest.shared</string>
  </array>
  <key>get-task-allow</key>
  <true/>
</dict>
</plist>
% security cms -D -i iOSTest.app/embedded.mobileprovision
…
<dict>
  <key>Entitlements</key>
  <dict>
    <key>application-identifier</key>
    <string>SKMME9E2Y8.com.example.apple-samplecode.iOSTest</string>
    <key>keychain-access-groups</key>
    <array>
        <string>SKMME9E2Y8.*</string>
    </array>
    <key>get-task-allow</key>
    <true/>
    <key>com.apple.developer.team-identifier</key>
    <string>SKMME9E2Y8</string>
    <key>com.apple.security.application-groups</key>
    <array>
        <string>group.com.example.apple-samplecode.iOSTest.shared</string>
    </array>
    <key>com.apple.developer.associated-domains</key>
    <string>*</string>

  </dict>
  …
</dict>
</plist>

Note how the group ID starts with group and only that group is allowlisted by the profile. Contrast this with a Mac app:

% codesign -d --entitlements :- MacTest.app
…
<dict>
  <key>com.apple.security.application-groups</key>
  <array>
    <string>SKMME9E2Y8.com.example.apple-samplecode.MacTest.shared</string>
  </array>
  …
</dict>
</plist>
% security cms -D -i MacTest.app/Contents/embedded.provisionprofile 
…
<dict>
  <key>Entitlements</key>
  <dict>
    <key>com.apple.application-identifier</key>
    <string>SKMME9E2Y8.*</string>
    <key>keychain-access-groups</key>
    <array>
        <string>SKMME9E2Y8.*</string>
    </array>        
    <key>com.apple.developer.team-identifier</key>
    <string>SKMME9E2Y8</string>
  </dict>
  …
</dict>
</plist>

Here the group ID starts with the Team ID and the App Groups entitlement (com.apple.security.application-groups) is not present in the profile at all.

This speaks to the way that groups are protected on the two platforms. On iOS the developer web site enforces group uniqueness, that is, the site prevents team B from using a group ID that’s assigned to team A. In contrast, on macOS.

  • Group IDs are prefixed with the Team ID solely to prevent collisions.

  • The Mac App Store prevents you from publishing an app that uses a group ID that’s in use by another team.

It also explains an oddity associated with keychain access. Consider this quote from Sharing Access to Keychain Items Among a Collection of Apps:

Application groups

When you collect related apps into an application group using the App Groups entitlement, they share access to a group container, and gain the ability to message each other in certain ways. Starting in iOS 8, the array of strings given by this entitlement also extends the list of keychain access groups.

There’s three things to note here:

  • Using a group ID as a keychain access group only works on iOS; it’s not supported on macOS because doing so would be insecure.

  • The Apple Groups entitlement must be allowlisted by a provisioning profile on iOS, and that process is what protects the keychain from unauthorised access.

  • The required group prefix means that these keychain access groups can’t collide with other keychain access groups, which all start with an App ID prefix (there’s also Apple-only keychain access groups that start with other prefixes, like apple).

In contrast, standard keychain access groups are protected the same way on both platforms (via the Keychain Access Groups entitlement, keychain-access-groups).


The above explains the mysterious messages you’re getting from taskgated. It’s absolutely correct here — the entitlement you’re trying to use, namely the App Groups entitlement, is not allowlisted by your profile — but that’s absolutely normal.

It also explains why your provisioning profile doesn’t include the App Groups entitlement. Unlike on iOS, that’s expected.

Coming back to the issue of sharing keychain items, the best way to do that is via the Keychain Access Groups entitlement. This works the same way on both platforms.

Having said that, I don’t think that’ll work in your case. Remember that a sysex runs as root and your app is running as a normal user. These users get different keychains, and AFAIK there’s no affordance for sharing keychain access groups between users.

My standard recommendation here is to avoid trying to share state via static means (the file system and the keychain) but instead key the state in one place (the sysex) and have the app work with that state dynamically (via XPC).

Share and Enjoy

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

Add a Comment

Replies

The App Groups mechanism works differently on macOS and iOS. Let me start by explaining that difference, after which I’ll come back to your specific issues.

IMPORTANT In this context I’m using macOS to refer to a native macOS app. In Mac Catalyst things behave as they do on iOS. Likewise for iOS Apps on Mac.

On iOS, App Groups must be allowlisted by your provisioning profile. The exact opposite is true on macOS, where there’s no way to allowlist your App Group with a profile.

Consider this iOS app:

% codesign -d --entitlements :- iOSTest.app
…
<dict>
  <key>application-identifier</key>
  <string>SKMME9E2Y8.com.example.apple-samplecode.iOSTest</string>
  <key>com.apple.developer.team-identifier</key>
  <string>SKMME9E2Y8</string>
  <key>com.apple.security.application-groups</key>
  <array>
    <string>group.com.example.apple-samplecode.iOSTest.shared</string>
  </array>
  <key>get-task-allow</key>
  <true/>
</dict>
</plist>
% security cms -D -i iOSTest.app/embedded.mobileprovision
…
<dict>
  <key>Entitlements</key>
  <dict>
    <key>application-identifier</key>
    <string>SKMME9E2Y8.com.example.apple-samplecode.iOSTest</string>
    <key>keychain-access-groups</key>
    <array>
        <string>SKMME9E2Y8.*</string>
    </array>
    <key>get-task-allow</key>
    <true/>
    <key>com.apple.developer.team-identifier</key>
    <string>SKMME9E2Y8</string>
    <key>com.apple.security.application-groups</key>
    <array>
        <string>group.com.example.apple-samplecode.iOSTest.shared</string>
    </array>
    <key>com.apple.developer.associated-domains</key>
    <string>*</string>

  </dict>
  …
</dict>
</plist>

Note how the group ID starts with group and only that group is allowlisted by the profile. Contrast this with a Mac app:

% codesign -d --entitlements :- MacTest.app
…
<dict>
  <key>com.apple.security.application-groups</key>
  <array>
    <string>SKMME9E2Y8.com.example.apple-samplecode.MacTest.shared</string>
  </array>
  …
</dict>
</plist>
% security cms -D -i MacTest.app/Contents/embedded.provisionprofile 
…
<dict>
  <key>Entitlements</key>
  <dict>
    <key>com.apple.application-identifier</key>
    <string>SKMME9E2Y8.*</string>
    <key>keychain-access-groups</key>
    <array>
        <string>SKMME9E2Y8.*</string>
    </array>        
    <key>com.apple.developer.team-identifier</key>
    <string>SKMME9E2Y8</string>
  </dict>
  …
</dict>
</plist>

Here the group ID starts with the Team ID and the App Groups entitlement (com.apple.security.application-groups) is not present in the profile at all.

This speaks to the way that groups are protected on the two platforms. On iOS the developer web site enforces group uniqueness, that is, the site prevents team B from using a group ID that’s assigned to team A. In contrast, on macOS.

  • Group IDs are prefixed with the Team ID solely to prevent collisions.

  • The Mac App Store prevents you from publishing an app that uses a group ID that’s in use by another team.

It also explains an oddity associated with keychain access. Consider this quote from Sharing Access to Keychain Items Among a Collection of Apps:

Application groups

When you collect related apps into an application group using the App Groups entitlement, they share access to a group container, and gain the ability to message each other in certain ways. Starting in iOS 8, the array of strings given by this entitlement also extends the list of keychain access groups.

There’s three things to note here:

  • Using a group ID as a keychain access group only works on iOS; it’s not supported on macOS because doing so would be insecure.

  • The Apple Groups entitlement must be allowlisted by a provisioning profile on iOS, and that process is what protects the keychain from unauthorised access.

  • The required group prefix means that these keychain access groups can’t collide with other keychain access groups, which all start with an App ID prefix (there’s also Apple-only keychain access groups that start with other prefixes, like apple).

In contrast, standard keychain access groups are protected the same way on both platforms (via the Keychain Access Groups entitlement, keychain-access-groups).


The above explains the mysterious messages you’re getting from taskgated. It’s absolutely correct here — the entitlement you’re trying to use, namely the App Groups entitlement, is not allowlisted by your profile — but that’s absolutely normal.

It also explains why your provisioning profile doesn’t include the App Groups entitlement. Unlike on iOS, that’s expected.

Coming back to the issue of sharing keychain items, the best way to do that is via the Keychain Access Groups entitlement. This works the same way on both platforms.

Having said that, I don’t think that’ll work in your case. Remember that a sysex runs as root and your app is running as a normal user. These users get different keychains, and AFAIK there’s no affordance for sharing keychain access groups between users.

My standard recommendation here is to avoid trying to share state via static means (the file system and the keychain) but instead key the state in one place (the sysex) and have the app work with that state dynamically (via XPC).

Share and Enjoy

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

Add a Comment

Thanks, you've cleared a lot about app-groups and keychain-access-groups, but what about all the other Security errors and NetworkExtension messages saying "Signature check failed: invalid signature (code or signature have been modified)", that are probably the main cause why the tunnel receives a fatal error?

The

code or signature have been modified
text is associated with error -67061, or
errSecCSSignatureFailed
. This generally means what it says: Something has broken the seal on the code signature. I most often see this when folks modify their code after signing it, or incorrectly re-sign things.

Are you building this project with Xcode? If so, you have any oddball build phases? Or post-build scripts?

Share and Enjoy

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

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

Is there a way to share an app group between a macOS and Catalyst app? Or does this difference mean it isn't possible? For context, I'm embedding a macOS app inside my Catalyst app so that I can add status menu items. I'd like to share some preferences from the Catalyst app with the macOS app. However, the Catalyst app group seems to require that the group ID start with group. while the macOS app needs the group ID to start with my team prefix.

If I use the team prefix in my Catalyst app, I get warnings:

Application Group identifiers should start with &#039;group.&#039;.

Provisioning profile "iOS Team Provisioning Profile: com.kylebashour.aqi-***" doesn&#039;t support the xxxxxxxxxx.group.com.kylebashour.aqi-*** App Group.

Provisioning profile "iOS Team Provisioning Profile: com.kylebashour.aqi-***" doesn&#039;t match the entitlements file&#039;s value for the com.apple.security.application-groups entitlement.

However... things build and the groups seem to sync. I can even archive and upload to App Store Connect. What's the best path forward here?

Is there a way to share an app group between a macOS and Catalyst app?

Yes. I collected together my app groups knowledge into another post: App Groups: macOS vs iOS: Fight!. Please read that through and, if you have follow-up questions, put them in a new thread (use the same tags as that post so that I see your thread).

Share and Enjoy

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