Endpoint security system extension misconfiguration

Hi All,

Starting from the SimpleFirewall Apple Network Extension example I managed to create an app with an Endpoint Security extension.


From the console I can see that the app is starting correctly and the System Extension is registered and loaded correctly by Sysextd:

attempting to realize extension with identifier com.***.***.endpoint


But then the system extensions fails with:

System extension request failed: Invalid extension configuration in Info.plist and/or entitlements


That is the same error I can see settings a breakpoint in:

    func request(_ request: OSSystemExtensionRequest, didFailWithError error: Error)


Note 1: My provisioning profile doesn't contain yet a com.apple.developer.endpoint-security.client (requested but not yet approved) but I removed it from the .entitlements file and added to the system extension info.plist, for development "should" be ok right?


Note 2: Keeping the entitlement in the .entitlements file but not having it in the Provisioning Profile obviously causes an error:

com.***.zuul: Unsatisfied entitlements: com.apple.developer.endpoint-security.client


What am I missing?


I noticed that the SimpleFirewall has a special configuration in the info.plist

<key>com.apple.developer.networking.networkextension</key>
  <array>
  <string>content-filter-provider</string>
  </array>

do I need to add something similar to the Endpoint Security?

Accepted Reply

First up, you should remove the App Sandbox entitlement (

com.apple.security.app-sandbox
). See this thread for info on the supported distribution models for the various flavours of system extensions.

Second, make sure you check the entitlements for your built binary, not your

.entitlements
file. The latter is just one input to the code signing process that sets up your actual entitlements.

For example, here’s the entitlements I have in a test project I use for this sort of thing:

$ codesign -d --entitlements :- NullEndpointSecurity.app
…
<dict>
    <key>com.apple.application-identifier</key>
    <string>SKMME9E2Y8.com.example.apple-samplecode.NullEndpointSecurity</string>
    <key>com.apple.developer.system-extension.install</key>
    <true/>
    <key>com.apple.developer.team-identifier</key>
    <string>SKMME9E2Y8</string>
    <key>com.apple.security.get-task-allow</key>
    <true/>
</dict>
</plist>
$
$ codesign -d --entitlements :- NullEndpointSecurity.app/Contents/Library/SystemExtensions/com.example.apple-samplecode.NullEndpointSecurity.Extension.systemextension
…
<dict>
    <key>com.apple.application-identifier</key>
    <string>SKMME9E2Y8.com.example.apple-samplecode.NullEndpointSecurity.Extension</string>
    <key>com.apple.developer.endpoint-security.client</key>
    <true/>
    <key>com.apple.developer.team-identifier</key>
    <string>SKMME9E2Y8</string>
    <key>com.apple.security.get-task-allow</key>
    <true/>
</dict>
</plist>

Third, disabling SIP should be sufficient for testing EndpointSecurity. Indeed, for a daemon that calls EndpointSecurity directly, disabling SIP is sufficient. However, if you’re building an EndpointSecurity system extension using Xcode, disabling SIP is not sufficient. We’re still investigating this (r. 57130762) but, in the meantime, you can get things working by first disabling SIP and then disabling AMFI:

$ sudo nvram boot-args="amfi_get_out_of_my_way=0x1”

IMPORTANT Do not disable SIP on a machine you care about. I do all of my EndpointSecurity testing in a VM, so I don’t have to disable SIP on my main work machine. If testing in a VM is insufficient, test on dedicated ‘victim’ hardware, not on your main Mac.

Fourth, the above is only relevant for testing. When you go to deploy, you must be granted the EndpointSecurity entitlement (

com.apple.developer.endpoint-security.client
) by Apple. That will whitelist the entitlement in your provisioning profile, at which point you’ll be able to run on standard user machines, those with SIP enabled.

Share and Enjoy

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

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

Replies

First things first, check that your bundle’s

CFBundlePackageType
property is
SYSX
. It’s easy to miss this, and it’ll give exactly the error you’re seeing.

If that’s not it, the problem is most likely with your entitlements. Your extension really needs the

com.apple.developer.endpoint-security.client
entitlement. If you haven’t yet been granted it by Apple, you should disable SIP on your test Mac, which allows you use the entitlement even though you don’t have a provisioning profile to whitelist it.

Share and Enjoy

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

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

Hi Eskimo,

Thank you for your answer.


I actually have SIP disabled and not having the entitlement granted by Apple I removed it fomr the .entitlements file and added to my endpoint security info.plist.


My CFBundlePackageType was $(PRODUCT_BUNDLE_PACKAGE_TYPE) and I changed it, just in case, to SYSX. Unfortunatelly the error is still there.


Here the logs I can see in the console filtering for "zuul" that is my prototype name:


default 17:08:05.468297+0000 secinitd Zuul[16986]: root path for bundle "<private>" of main executable "<private>"
default 17:08:05.615951+0000 secinitd Zuul[16986]: AppSandbox request successful
default 17:08:05.648643+0000 Zuul FRONTLOGGING: version 1
default 17:08:05.648670+0000 Zuul Registering, pid=16986
default 17:08:05.650254+0000 Zuul CHECKIN: pid=16986
default 17:08:05.661792+0000 Zuul CHECKEDIN: pid=16986 asn=0x0-0x1b11b1 foreground=0
default 17:08:05.660769+0000 launchservicesd CHECKIN:0x0-0x1b11b1 16986 com.xxxxxxxx.zuul
default 17:08:05.662844+0000 loginwindow -[ApplicationManager checkInAppContext:eventData:] | ApplicationManager: Checked in app : Zuul
default 17:08:05.664459+0000 runningboardd Resolved pid 16986 to [executable<Zuul(501)>:16986]
default 17:08:05.666172+0000 runningboardd [executable<Zuul(501)>:16986] This process will not be managed.
default 17:08:05.666213+0000 runningboardd Now tracking process: [executable<Zuul(501)>:16986]
default 17:08:05.666753+0000 runningboardd Acquiring assertion targeting executable<Zuul(501)> from originator [daemon<com.apple.coreservices.launchservicesd>:213] with description <RBSAssertionDescriptor; uielement:16986; ID: 349-213-1893; target: 16986> attributes = {
    <RBSDomainAttribute: 0x7fac5743a380; domain: com.apple.launchservicesd; name: RoleUserInteractive; sourceEnvironment: 0x0>;
}
default 17:08:05.666902+0000 runningboardd Assertion 349-213-1893 (target:executable<Zuul(501)>) will be created as active
default 17:08:05.667510+0000 runningboardd [executable<Zuul(501)>:16986] Ignoring jetsam update because this process is not memory-managed
default 17:08:05.667515+0000 runningboardd Acquiring assertion targeting executable<Zuul(501)> from originator [daemon<com.apple.coreservices.launchservicesd>:213] with description <RBSAssertionDescriptor; uielement:16986; ID: 349-213-1894; target: 16986> attributes = {
    <RBSDomainAttribute: 0x7fac57718db0; domain: com.apple.launchservicesd; name: RoleUserInteractive; sourceEnvironment: 0x0>;
}
default 17:08:05.667653+0000 runningboardd [executable<Zuul(501)>:16986] Ignoring resume because this process is not lifecycle managed
default 17:08:05.667879+0000 runningboardd [executable<Zuul(501)>:16986] Set darwin role to: UserInteractive
default 17:08:05.667845+0000 runningboardd Assertion 349-213-1894 (target:executable<Zuul(501)>) will be created as active
default 17:08:05.668214+0000 runningboardd [executable<Zuul(501)>:16986] Ignoring GPU update because this process is not GPU managed
default 17:08:05.668366+0000 runningboardd Finished acquiring assertion 349-213-1893 (target:executable<Zuul(501)>)
default 17:08:05.669126+0000 runningboardd Finished acquiring assertion 349-213-1894 (target:executable<Zuul(501)>)
default 17:08:05.669132+0000 runningboardd Invalidating assertion 349-213-1893 (target:executable<Zuul(501)>) from originator 213
default 17:08:05.673136+0000 *** Non-fatal error enumerating at <private>, continuing: Error Domain=NSCocoaErrorDomain Code=260 "The file “PlugIns” couldn’t be opened because there is no such file." UserInfo={NSURL=PlugIns/ -- file:///Users/kappe/Library/Developer/Xcode/DerivedData/Zuul-fktseybbsnrtfwclzgucnkeddlvj/Build/Products/Debug/Zuul.app/Contents/, NSFilePath=/Users/kappe/Library/Developer/Xcode/DerivedData/Zuul-fktseybbsnrtfwclzgucnkeddlvj/Build/Products/Debug/Zuul.app/Contents/PlugIns, NSUnderlyingError=0x7f89a962bf50 {Error Domain=NSPOSIXErrorDomain Code=2 "No such file or directory"}}
default 17:08:05.673223+0000 *** - 45683955: Checking whether application is managed at file:///Users/kappe/Library/Developer/Xcode/DerivedData/Zuul-fktseybbsnrtfwclzgucnkeddlvj/Build/Products/Debug/Zuul.app//com.xxxxxxxx.zuul
default 17:08:05.676450+0000 Zuul Registered, pid=16986 ASN=0x0,0x1b11b1
default 17:08:05.676589+0000 Zuul Registered, pid=16986 cgConnectionID=182b3
default 17:08:05.678198+0000 Zuul BringForward: pid=16986 asn=0x0-0x1b11b1 bringForward=0 foreground=0 uiElement=1 launchedByLS=0 modifiersCount=0 allDisabled=0
default 17:08:05.679060+0000 Zuul Current system appearance, (HLTB: 2), (SLS: 1)
default 17:08:05.682432+0000 Zuul Post-registration system appearance: (HLTB: 2)
default 17:08:05.695189+0000 distnoted register name: com.apple.xctest.FakeForceTouchDevice object: com.xxxxxxxx.zuul token: f4268 pid: 16986
default 17:08:05.706321+0000 Zuul NSApp cache appearance:
-NSRequiresAquaSystemAppearance: 0
-appearance: (null)
-effectiveAppearance: <NSCompositeAppearance: 0x600002c03b00
 (
    "<NSDarkAquaAppearance: 0x600002c01700>",
    "<NSSystemAppearance: 0x600002c03c00>"
)>
default 17:08:05.706978+0000 distnoted register name: com.apple.nsquiet_safe_quit_give_reason object: com.xxxxxxxx.zuul token: f426e pid: 16986
default 17:08:05.738362+0000 Zuul Registering for test daemon availability notify post.
default 17:08:05.738528+0000 Zuul notify_get_state check indicated test daemon not ready.
default 17:08:05.745275+0000 Zuul SignalReady: pid=16986 asn=0x0-0x1b11b1
default 17:08:05.746018+0000 Zuul SIGNAL: pid=16986 asn=0x0x-0x1774001
error 17:08:05.754288+0000 appleeventsd <rdar://problem/11489077> A sandboxed application with pid 16986, '"Zuul"', checked in with appleeventsd, but its code signature could not be read and validated by appleeventsd, and so it cannot receive AppleEvents targeted by name, bundle id, or signature. Install the application in /Applications/ or some other world readable location to resolve this issue. Error=ERROR: #100013  { "NSDescription"="SecCodeCopySigningInformation() returned 100013, -." }
default 17:08:05.779423+0000 tccd -[TCCDAccessIdentity staticCode]: static code for: identifier com.xxxxxxxx.zuul, type: 0: 0x7fc893e14470 at /Users/kappe/Library/Developer/Xcode/DerivedData/Zuul-fktseybbsnrtfwclzgucnkeddlvj/Build/Products/Debug/Zuul.app
default 17:08:05.788781+0000 Zuul Start
default 17:08:05.844101+0000 sysextd attempting to realize extension with identifier com.xxxxxxxx.zuul.endpoint
default 17:08:05.861742+0000 Zuul System extension request failed: Invalid extension configuration in Info.plist and/or entitlements
default 17:08:15.693908+0000 Zuul LSExceptions shared instance invalidated for timeout.


The interesting ones are the last 3 messages:


sysextd attempting to realize extension with identifier com.xxxxxxxx.zuul.endpoint
Zuul System extension request failed: Invalid extension configuration in Info.plist and/or entitlements


this is the EndpointSecurity 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>CFBundleDevelopmentRegion</key>
  <string>$(DEVELOPMENT_LANGUAGE)</string>
  <key>CFBundleDisplayName</key>
  <string>ZuulEndpoint</string>
  <key>CFBundleExecutable</key>
  <string>$(EXECUTABLE_NAME)</string>
  <key>CFBundleIdentifier</key>
  <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
  <key>CFBundleInfoDictionaryVersion</key>
  <string>6.0</string>
  <key>CFBundleName</key>
  <string>$(PRODUCT_NAME)</string>
  <key>CFBundlePackageType</key>
  <string>SYSX</string>
  <key>CFBundleShortVersionString</key>
  <string>1.0</string>
  <key>CFBundleVersion</key>
  <string>1</string>
  <key>LSMinimumSystemVersion</key>
  <string>$(MACOSX_DEPLOYMENT_TARGET)</string>
  <key>NSHumanReadableCopyright</key>
  <string>Copyright © 2019 xxxxxx. All rights reserved.</string>
  <key>NSSystemExtensionUsageDescription</key>
  <string>Test test test TODO</string>
  <key>com.apple.developer.endpoint-security.client</key>
  <true/>
</dict>
</plist>


Do you have any idea on how to solve this? I'm filing an improvement request for the documentation and for an xcode template.

Thank you

I actually have SIP disabled

cool.

and not having the entitlement granted by Apple I removed it [from] the

.entitlements
file and added to my endpoint security
info.plist
.

Huh? Can you point me at the place where that technique is documented? Because it doesn’t gel with my understanding of how this stuff works.

Share and Enjoy

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

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

I am having the same issues as kappe_m. I have gotten the SimpleFirewall app running and am now trying to replace the extension target to run code with the EndpointSecurity framework, instead of network extensions framework, but cannot get the extension to run. It doesn't even come up enough to log an initial message.


I see these messages in the console:

default 17:43:43.251820-0800 EndpointSecurityApp Extension com.xxxx.test.yyyy requires user approval
default 17:44:02.875067-0800 sysextd notifying categories that extension com.xxxx.test.yyyy will start
default 17:44:02.875662-0800 sysextd request to enable/disable com.xxxx.test.yyyy finishing successfully
default 17:44:02.875938-0800 sysextd starting extension com.xxxx.test.yyyy via owning category
default 17:44:02.881197-0800 sysextd Extension point confirmed that extension com.xxxx.test.yyyy is runnable.
default 17:44:02.881243-0800 sysextd changing state of extension com.xxxx.test.yyyy to activated_enabled.
default 17:44:02.901637-0800 taskgated-helper Checking profile: Mac Team Provisioning Profile: com.xxxx.test.yyyy
error 17:44:02.901909-0800 taskgated-helper com.xxxx.test.yyyy: Unsatisfied entitlements: com.apple.developer.endpoint-security.client
error 17:44:02.902107-0800 taskgated-helper Disallowing: com.xxxx.test.yyyy
default 17:44:02.904283-0800 kernel proc 61171: load code signature error 4 for file "com.xxxx.test.yyyy"

I have added com.apple.developer.endpoint-security.client to the entitlements file for my extension target, disabled SIP, and set the CFBundlePackageType property to SYSX in the info.plist. Like kappe_m, we have requested but not yet gotten approval for the endpoint-security entitlement in our provisioning profile.


Do I have to wait for the approval before my extension will even work in debug mode? Is that my problem?


Here is my app target entitlement:

<dict>

<key>com.apple.security.app-sandbox</key>

<true/>

<key>com.apple.security.files.user-selected.read-only</key>

<true/>

<key>com.apple.developer.system-extension.install</key>

<true/>

<key>com.apple.security.application-groups</key>

<array>

<string>$(TeamIdentifierPrefix) com.example.app-group.EndpointSecurityApp</string>

</array>

</dict>



Here is my extension target entitlement:

<dict>

<key>com.apple.security.app-sandbox</key>

<true/>

<key>com.apple.security.application-groups</key>

<array>

<string>$(TeamIdentifierPrefix)com.example.app-group.EndpointSecurityApp</string>

</array>

<key>com.apple.developer.endpoint-security.client</key>

<true/>

</dict>


Thanks for any help.

First up, you should remove the App Sandbox entitlement (

com.apple.security.app-sandbox
). See this thread for info on the supported distribution models for the various flavours of system extensions.

Second, make sure you check the entitlements for your built binary, not your

.entitlements
file. The latter is just one input to the code signing process that sets up your actual entitlements.

For example, here’s the entitlements I have in a test project I use for this sort of thing:

$ codesign -d --entitlements :- NullEndpointSecurity.app
…
<dict>
    <key>com.apple.application-identifier</key>
    <string>SKMME9E2Y8.com.example.apple-samplecode.NullEndpointSecurity</string>
    <key>com.apple.developer.system-extension.install</key>
    <true/>
    <key>com.apple.developer.team-identifier</key>
    <string>SKMME9E2Y8</string>
    <key>com.apple.security.get-task-allow</key>
    <true/>
</dict>
</plist>
$
$ codesign -d --entitlements :- NullEndpointSecurity.app/Contents/Library/SystemExtensions/com.example.apple-samplecode.NullEndpointSecurity.Extension.systemextension
…
<dict>
    <key>com.apple.application-identifier</key>
    <string>SKMME9E2Y8.com.example.apple-samplecode.NullEndpointSecurity.Extension</string>
    <key>com.apple.developer.endpoint-security.client</key>
    <true/>
    <key>com.apple.developer.team-identifier</key>
    <string>SKMME9E2Y8</string>
    <key>com.apple.security.get-task-allow</key>
    <true/>
</dict>
</plist>

Third, disabling SIP should be sufficient for testing EndpointSecurity. Indeed, for a daemon that calls EndpointSecurity directly, disabling SIP is sufficient. However, if you’re building an EndpointSecurity system extension using Xcode, disabling SIP is not sufficient. We’re still investigating this (r. 57130762) but, in the meantime, you can get things working by first disabling SIP and then disabling AMFI:

$ sudo nvram boot-args="amfi_get_out_of_my_way=0x1”

IMPORTANT Do not disable SIP on a machine you care about. I do all of my EndpointSecurity testing in a VM, so I don’t have to disable SIP on my main work machine. If testing in a VM is insufficient, test on dedicated ‘victim’ hardware, not on your main Mac.

Fourth, the above is only relevant for testing. When you go to deploy, you must be granted the EndpointSecurity entitlement (

com.apple.developer.endpoint-security.client
) by Apple. That will whitelist the entitlement in your provisioning profile, at which point you’ll be able to run on standard user machines, those with SIP enabled.

Share and Enjoy

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

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

Thanks, Eskimo! Your suggestions did the trick. My extension is now running!

Hi Eskimo. Do you have any insight into how long it takes to get the EndpointSecurity entitlement added to our developer key? Do you have any advice on getting it through faster? We submitted the request and got the auto-response but have not heard back yet. The Follow-up code is 724466507.

Do you have any insight into how long it takes to get the EndpointSecurity entitlement added to our developer key?

No, sorry.

Share and Enjoy

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

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

ps DTS is closed 25…29 Nov in observance of the US Thanksgiving holiday.

Hello,


I have done all suggested configuration in my application and System Extension for Enspoint security. I am able to activate and deactivate extensions, but not able to call 'System Extension''s main() function.


Can anyone please guide me what will be the entry point (initial function / delegate) of System Extension? where can I initialize es_client related task?


--

Thank you

By follwing steps from WWDC System Extension video and some of the steps provided by eskimo I am able to build and run SystemExtension successfully.

Thanks eskimo for the details.


Happy Coding

@eskimo it would be great to have info about AMFI in docs https://developer.apple.com/documentation/driverkit/debugging_and_testing_system_extensions

Endpoint Security ext wouldn't had started on my machine even with disabled SIP. Disabling AMFI helped, so it feels like kinda important instruction