I have a process [command line cpp application] which i want to run always such as it should relaunch after a crash, after device startup etc.
I created a launchd Property List File with KeepAlive true and placed under /Library/LaunchDaemons.
Problem Statements:
I have a bash script to start and stop this process.
start using: launchctl bootstrap.
stop involve these two steps:
send SIGTERM signal and wait untill process stops after doing some cleanups
launchctl bootout [It doesn't sends SIGTERM]
during steps 1 - Process is getting stop, but also getting immediate relaunch by launchctl
during step 2 - it getting stop again.
is there a proper way so that we can disable KeepAlive temporarily so that process will not launch during step 1?
or suggest other ways to handle this?
Endpoint Security
RSS for tagDevelop system extensions that enhance user security using Endpoint Security.
Posts under Endpoint Security tag
79 Posts
Sort by:
Post
Replies
Boosts
Views
Activity
I'm working on a system extension leveraging endpoint security entitlement. However, while in development, is there a way to continue working and testing locally without having the endpoint security entitlement approved or needing the extension signed.
I got these errors running a build:
Provisioning profile "Mac Team Provisioning Profile: "com.xxxxx.extension" doesn't include the com.apple.developer.endpoint-security.client entitlement.
Firstly, I want to keep my GUI app available for download on the Mac App Store, which means I need to provide the Endpoint Security functionality in some other executable, such as a daemon.
I'm going to use a User Agent for user-aware background processing.
Instead of the typical use of adding an Endpoint Security system extension to a macOS app, could I instead add the sysex to my User Agent bundle?
I like the benefits of coupling the sysex to the client that will interact with it, and this would also allow me to not have to worry about managing a daemon. I could simply provide the User Agent in a downloadable installer signed with my Developer ID certificate.
Trying to flesh out an idea for an application which would rely on Endpoint Security Framework and Network Extension Framework, where intend the application to:
Forward certain ESF events to a backend (on a separate server)
Forward certain Unified logs to a backend (on a separate server)
Forwarding various DNS queries and responses (on a separate server)
Retrieve configuration from the backend to set Network Extension Filters
Are there any limitations and/or reasons not to bundle all this functionality into a single system extension?
I know of other applications where system extension is very thin and main application (daemon) communicates over xpc with the system extension, would this be considered best practice?
We’re encountering issues with a system extension that subscribes to multiple events. Some users are experiencing performance problems when running our extension alongside other system extensions like Microsoft Defender and Crowdstrike, which seem to generate a high volume of events. However, on certain Macs with an identical setup, there are no performance issues, making it difficult to pinpoint the cause.
Has anyone found ways to improve compatibility with other system extensions? Currently, we’re ignoring and caching events from other extensions to avoid unnecessary processing.
The specific ES events contributing to the issue seem to be:
• ES_EVENT_TYPE_AUTH_EXEC
• ES_EVENT_TYPE_AUTH_OPEN
I realize this is a broad question, but the documentation for endpoint security extensions is quite limited. Any insights or suggestions would be greatly appreciated!
Hey folks,
I developed a DLP program based on Endpoint Security for the enterprise, and everything functioned normally. I also applied for the development permission of Endpoint Security before, which took 3 months. Now I want to distribute the software internally, so I tried to apply for a certificate for distribution permission. After waiting for 3 months, Apple told me that the permission was rejected.
This is the replay content:
Thank you for your interest in Endpoint Security. After carefulconsideration, we regret that we're unable to approve your request at this time. If you'd like to submit another request for this capability, please review andconfirm that your app details and justification meet the criteria before resubmittting.
Rejecting duplicate request.
Apple Developer Relations
I don't know what's wrong, what should I do to get distribution or developer id permissions.
I try to mix content filter and endpoint security in one system extension, but get error below when the program invoke es_new_client(returned ES_NEW_CLIENTRESULT_ERR_INTERNAL).
Failed to open services: 0xe00002e2: Caller was denied connecting to the ES subsystem, possibly due to a sandbox violation.
how to solve this error while keeping two functionalities in one system extension?
or I have to seperate them?
I think there's a slight discrepancy between what is being communicated in EndpointSecurity docs, and what is really happening.
For example, consider the description of this event:
https://developer.apple.com/documentation/endpointsecurity/es_event_type_t/es_event_type_notify_truncate?language=objc
"ES_EVENT_TYPE_NOTIFY_TRUNCATE: An identifier for a process that notifies endpoint security that it is truncating a file."
But, it seems that this event is fired up only when truncate(2) is called, not when process truncates a file (which can be done in lots of different ways). But the documentation doesn't even mention that it's only about the truncate(2) call, it's impossible to know.
Another example:
https://developer.apple.com/documentation/endpointsecurity/es_event_type_t/es_event_type_notify_copyfile?language=objc
"ES_EVENT_TYPE_NOTIFY_COPYFILE: An identifier for a process that notifies endpoint security that it is copying a file."
It seems that this event is only called when copyfile(3) syscall is called. But the docs doesn't mention that syscall at all. The wording suggests that the event should be emitted on every file copy operation, which is probably impossible to detect.
I mean, I get that you'd like the docs to be "easy to digest", but I think that such working confuses people. They expect one thing, then they get confusing behavior from ES, because it doesn't match their expectations, and after reaching out to Apple they get concise and clear answer -- but it would be easier for everyone (including Apple devs) when this answer would be included directly in the official docs for the framework.
The kernel sends SIGKILL to application if it handles ES_EVENT_TYPE_AUTH_OPEN and lldb is attached to this process.
App:
int main(int /*argc*/, char** /*argv*/)
{
es_client_t *pEpClient = nullptr;
es_new_client_result_t result = es_new_client(&pEpClient, ^(es_client_t *pClient, const es_message_t *pMessage)
{
switch (pMessage->event_type)
{
case ES_EVENT_TYPE_AUTH_OPEN:
{
uint32_t authorizedFlags = pMessage->event.open.fflag;
if ((authorizedFlags & FREAD) || (authorizedFlags & FWRITE))
{
std::filesystem::path filePath = std::string(pMessage->event.open.file->path.data, pMessage->event.open.file->path.length);
std::string fileName = filePath.filename();
if (fileName == "test.txt")
{
std::cout << "blocked fileName: " << filePath.filename() << std::endl;
authorizedFlags &= ~FWRITE;
authorizedFlags &= ~FREAD;
}
}
if (es_respond_flags_result(pClient, pMessage, authorizedFlags, false) != ES_RESPOND_RESULT_SUCCESS)
{
std::cout << "es_respond_flags_result() failed with error " << std::endl;
}
}
break;
default:
break;
}
});
if (result != ES_NEW_CLIENT_RESULT_SUCCESS)
{
std::cout << "es_new_client() failed." << std::endl;
return 1;
}
es_event_type_t eventsList[] =
{
ES_EVENT_TYPE_AUTH_OPEN
};
if (es_subscribe(pEpClient, eventsList, 1) == ES_RETURN_ERROR)
{
std::cout << "es_subscribe() failed." << std::endl;
}
// wait
int i = 0;
std::cin >> i;
if (es_delete_client(pEpClient) == ES_RETURN_ERROR)
{
std::cout << "es_delete_client() failed." << std::endl;
}
return 0;
}
(lldb) process attach --pid 61127
....
(lldb) c
Process 61127 resuming
Process 61127 exited with status = 9 (0x00000009) Terminated due to signal 9
System log:
Allowing set_exception_ports from [debugserver] on [ep_sample] for entitled process/debugger
Client did not respond in appropriate amount of time (client pid: 61127), sent SIGKILL
I'm seeing some odd behavior which may be a bug. I've broken it down to a least common denominator to reproduce it. But maybe I'm doing something wrong.
I am opening a file read-write. I'm then mapping the file read-only and private:
void* pointer = mmap(NULL, 17, PROT_READ, MAP_FILE | MAP_PRIVATE, fd, 0);
I then unmap the memory and close the file. After the close, eslogger shows me this:
{"close":{"modified":false,[...],"was_mapped_writable":false}}
Which makes sense.
I then change the mmap statement to:
void* pointer = mmap(NULL, 17, PROT_READ, MAP_FILE | MAP_SHARED, fd, 0);
I run the new code and and the close looks like:
{"close":{"modified":false, [....], "was_mapped_writable":true}}
Which also makes sense.
I then run the original again (ie, with MAP_PRIVATE vs. MAP_SHARED) and the close looks like:
{"close":{"modified":false,"was_mapped_writable":true,[...]}
Which doesn't appear to be correct.
Now if I just open and close the file (again, read-write) and don't mmap anything the close still shows:
{"close":{ [...], "was_mapped_writable":true,"modified":false}}
And the same is true if I open the file read-only.
It will remain that way until I delete the file. If I recreate the file and try again, everything is good until I map it MAP_SHARED.
I tried this with macOS 13.6.7 and macOS 15.0.1.
Good day. As part of a business unit separation, we are required to have our product with a different name, bundle IDs and certificates than our current configuration.
The product contains network extensions and requires Full Disk Access. We distribute this product to our customers who either support MDM or not.
I know from previous experience that a product can be transferred to a different account, which is something we could do only for some parts of our product (only a couple of Bundle IDs).
My question is what's the best way to do this. I can imagine that having a scripted scenario where the other business unit's product is removed from customers and ours is installed, in a different folder.
The main issue I can foresee is that because our architecture uses several network extensions that are installed as plugins (bad design I know), we would be asking the users for authorisation, again, to use those extensions, plus full disk access.
What options do I have?
In the man page for the eslogger tool, there is a reference to the jq tool.
Postprocess the output in a shell pipeline with jq:
% sudo eslogger exec | jq -r 'select(.process.executable.path ==
"/bin/zsh")|"(.process.audit_token.pid): (.process.executable.path) -(.event.exec.target.executable.path)"'
The problem is that the jq tool is not installed by default with macOS.
[Q] Isn't the idea that the man page should only reference tools that are part of the standard macOS distribution (or can be downloaded and installed by the OS when you try to run them, like with some developer tools)?
I've developed a Endpoint Security system extension, which will be installed in a container APP.
I use XPC to send message from container APP to the ES client, it works fine.
I have developed an Endpoint Security system extension that will be installed in a container app.
I utilize XPC to send messages from the container app to the ES client, and it functions properly. However, when I attempt to send messages from the ES client to the container app, it always displays an error: 'Couldn’t communicate with a helper application.'.
I have removed the sandbox capability of the container app and also employed the same app group for both the ES client and the container app. When an XPC client is connected, I use the following code in the ES client to establish two-way communication.
- (BOOL)listener:(NSXPCListener *)listener shouldAcceptNewConnection:(NSXPCConnection *)newConnection {
newConnection.exportedInterface = [NSXPCInterface interfaceWithProtocol:@protocol(NXFileGuardXPCProtocol)];
NXFileGuardXPCService *xpcService = [NXFileGuardXPCService sharedInstance];
newConnection.exportedObject = xpcService;
// To APP container client (As remote interface)
newConnection.remoteObjectInterface = [NSXPCInterface interfaceWithProtocol:@protocol(NXFileGuardXPCClientProtocol)];
[newConnection activate];
self.containerAPPConnection = newConnection;
return YES;
}
But it always fails. How can I deal with this error?
Hi Team,
In previous macOS version, We were using this link to open system extension permission page programmatically for our swift app. x-apple.systempreferences:com.apple.preference.security?General
In macos 15 (Sequoia), this pane is moved to system settings-> general->login Items and extensions->end point security extensions which is a modal/popup.
Can you please share what should be link to open exact this popup for asking permissions.It appears when you click on i button against end point security extensions
Based on apple script I could find following link but it opens login item & extensions pane, I want the next popup as above screenshot.
"x-apple.systempreferences:com.apple.LoginItems-Settings.extension?extensionItems™
Hi Team,
I am trying to explore ESF events specifically generated by cloudsync extensions built on File Provider framework.
Brief:
I have high-level understanding of how various cloud vendors have provided their extensions to sync data from cloud/remote storage to local filesystem (and vice-versa). e.g.iCloudDriveFileProvider (icloud), DFSFileProviderExtension (google drive).
There are 2 ESF AUTH events for file provider I can see namely: ES_EVENT_TYPE_AUTH_FILE_PROVIDER_MATERIALIZE ,
ES_EVENT_TYPE_AUTH_FILE_PROVIDER_UPDATE.
and respectively their NOTIFY events.
Observation:
Observed that these events are generally triggered by fileproviderd process during download scenario i.e. syncing files from cloud/remote storage to local file system. i.e. 'materialize' for new file creation and 'update' for updating existing file.
Question/Problem:
Is there a correct way to find which cloud provider has triggered this download event? i.e. weather it is iCloudDriveFileProvider or DFSFileProviderExtension (there is this instigator field in Materialize event struct, but could not find similar for Update event.
Are there similar ESF events for upload scenario? (I have fair understanding of how file-to-upload is copied to temp location and then uploaded by respective extensions to remote storage, but then they work with original files clone created in their temp location, so the AUTH events generated by this extension will wont reveal the original file name even if I am able to get the Fileprovider name)
To Summarize: Basically I am looking for ESF event that will be triggered during upload scenario that can also let me know original file name as well the cloudprovider extension process name. As of now 'fileproviderd' process name is obtained from filesystem ESF events like AUTH_OPEN etc.
I tried to use XCTest to test my own project that uses EndpointSecurity, but when I created the esClient I got an error:ES_NEW_CLIENT_RESULT_ERR_NOT_PRIVILEGED, indicating that it was not root.
This makes it impossible for me to do coverage tests for the ESClient application. Is there any way I can implement this ESClient test? If so, how should I use it? The project is a macOS program, if I use gcov, but I find I can't get coverage. Using __gcov_flush will indicate that there is no symbol
#if !TARGET_IPHONE_SIMULATOR
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
setenv("GCOV_PREFIX", [documentsDirectory cStringUsingEncoding:NSUTF8StringEncoding], 1);
setenv("GCOV_PREFIX_STRIP", "13", 1);
#endif
extern void __gcov_flush(void);
__gcov_flush();
#endif
Is it known how to open in macOS Sequoia the Endpoint Security Extensions Pane. is there any anchor available for
open "x-apple.systempreferences:com.apple.ExtensionsPreferences"?
Hello,
I am working on app which must prevent attaching any USB devices to Mac due to security.
Unfortunately I have not found any direct way to implement such blocking:
Looks like IOKit does not allow to block USB (at least in user space)
ES_EVENT_TYPE_AUTH_IOKIT_OPEN (Endpoint Security) does not prevent using USB device if I send response ES_AUTH_RESULT_DENY for "AppleUSBHostDeviceUserClient"
I have found several similar problems on forum but no any solution:
https://developer.apple.com/forums/thread/671193
(https://developer.apple.com/forums/thread/756573
https://developer.apple.com/forums/thread/741051
What is the easiest way to implement such blocking?
Thank you in advance!
I'm writing ES client, as part of that I want to monitor when an user is being added/removed to/from a group. From my understanding I should be able to get the name of the user with
msg->event.od_group_remove->member->member_value.name.data
but it looks like this field gets populated randomly. I will trigger similiar event a couple of times, for example adding user to a group and on one occasion this will hold value, on another it will be empty.
I also tried to check different fields, and surprisingly
od_create_user->user_name
holds the name of the group I am editing, not the name of the user I am adding to the group (but I'm not sure if it should even be engaged at this point).
Am I missing something? Is there a workaround? Or is this a bug?
hi, all
I subscribe AUTH_SIGNAL event with ESF.
and test if it can prevent Activity Monitor from killing processes in the list below.
I can stop "Force Quit"(sigkill) to all five processes, but "Quit"(sigterm?)
to four processes except "Typora".
I'm pretty sure that I didn't get a signal event when I used Activity Monitor to "Quit" typora.
how Activity Monitor "Quit" the "Typora"?
it looks like the Activity Monitor "Quit" the App Process with a different way(not through sending signal).