Here are the logs with the profile installed, it indeed revealed a single extra line related to Service Management before both my SMJobRemove and SMJobSubmit calls:
authd default com.apple.Authorization 2024-12-20 00:40:35.015306 -0800 authd Succeeded authorizing right 'com.apple.ServiceManagement.daemons.modify' by client ‘redacted/path/tp/RedactedAppName.app' [874] for authorization created by ‘redacted/path/to/RedactedAppName.app' [874] (3,0) (engine 31)
error com.apple.os_debug_log 2024-12-20 00:40:35.018568 -0800 RedactedAppName assertion failed: 23G93: ServiceManagement + 24216 [A64F7B28-7DFF-3137-A74B-BEB900AE33A2]: 0xffffffffffff159e
app error com.redacted.redactedAppName 2024-12-20 00:40:35.018699 -0800 RedactedAppName Failed to remove job! [Error Domain=CFErrorDomainLaunchd Code=2 "(null)"]
app debug com.redacted.redactedAppName 2024-12-20 00:40:35.018888 -0800 RedactedAppName Job's property list is [["ProgramArguments": <__NSArrayI 0x6000002a5880>(
/redacted/path/to/RedactedAppName.app/Contents/MacOS/redactedDaemonName,
—redactedFlagPassedToExecutable
)
, "KeepAlive": 0, "Label": com.redacted.redactedAppName.redactedDaemonName, "RunAtLoad": 1]].
app default com.redacted.redactedAppName 2024-12-20 00:40:35.018913 -0800 RedactedAppName Will not re-request authorization right, already got it.
error com.apple.os_debug_log 2024-12-20 00:40:35.019021 -0800 RedactedAppName assertion failed: 23G93: ServiceManagement + 24216 [A64F7B28-7DFF-3137-A74B-BEB900AE33A2]: 0xffffffffffff159e
app error com.redacted.redactedAppName 2024-12-20 00:40:35.019047 -0800 RedactedAppName Failed to submit job! [Error Domain=CFErrorDomainLaunchd Code=2 "(null)"]
logging info com.apple.libspindump 2024-12-20 00:40:35.019144 -0800 RedactedAppName Reporting HID response delay 4657124658-4743569411
connection default com.apple.xpc 2024-12-20 00:40:35.019155 -0800 RedactedAppName [0x600003dc1c20] activating connection: mach=true listener=false peer=false name=com.apple.spindump
logging info com.apple.spindump 2024-12-20 00:40:35.019840 -0800 spindump RedactedAppName [874]: slow hid response: start, <private> 4657124658-4743569411: 3.6s (threshold 0.5s)
logging default com.apple.spindump 2024-12-20 00:40:35.021972 -0800 spindump RedactedAppName [874]: slow hid response: not sampling due to conditions 0x8002
logging info com.apple.spindump 2024-12-20 00:40:35.025126 -0800 spindump RedactedAppName [874]: spin stop
logging info com.apple.spindump 2024-12-20 00:40:35.025181 -0800 spindump RedactedAppName [874]: Didn't receive spin start notification when we want to see spins, turning spin notifications on
cas info com.apple.launchservices 2024-12-20 00:40:35.026494 -0800 launchservicesd Moving App:"RedactedAppName" asn:0x0-41041 pid:874 refs=9 @ 0x12c7605d0 to front of visible list.
cas info com.apple.launchservices 2024-12-20 00:40:35.026702 -0800 launchservicesd SetFrontReservationExists(), newValue=NO, app=App:"RedactedAppName" asn:0x0-41041 pid:874 refs=9 @ 0x12c7605d0 ( was YES)
particularly these two lines:
assertion failed: 23G93: ServiceManagement + 24216 [A64F7B28-7DFF-3137-A74B-BEB900AE33A2]: 0xffffffffffff159e
and
assertion failed: 23G93: ServiceManagement + 24216 [A64F7B28-7DFF-3137-A74B-BEB900AE33A2]: 0xffffffffffff159e
seem to be interesting, however they provide no immediate extra information to me (other than 23G93 is the macOS version I'm running, 14.6.1). I'm hoping it might make more sense to you.
Post
Replies
Boosts
Views
Activity
Thank you Kevin for your detailed answer, however there are a few points I don't fully understand so I would appreciate some more clarity around them.
Stop using SMJobSubmit. That API was deprecated in 10.10 (seven years ago) and I believe we'd been recommending against it for several years.
To my knowledge SMJobSubmit is the only way other than AuthorizationExecuteWithPrivileges (an even older API) that allows one to get one-time throwaway root permissions to run a single executable. I'm saying this based on your colleague's answer here, and his very extensive and educational post here.
Your recommended replacement, SMAppService, is vastly different from SMJobSubmit:
It's not possible to gain one-time privileges, other than a very awkward solution of registering a daemon and having the daemon clean up itself in some way.
Registering a daemon is a very unfriendly user experience: the user sees an extremely small notification in the top right corner (if they even see it), where they must hover to even reveal the in-notification button to approve the daemon or have to directly go to system settings and approve the daemon.
I trust we can agree how much better of an API SMJobSubmit is from user experience sense.
Sadly, the first point above is also true for SMJobBless - it's a long shot for such a simple thing as running an executable once. Not to mention, to this day, this is the documentation header for SMJobSubmit, copied from the macOS 15.2 SDK:
@discussion
This routine is deprecated and will be removed in a future release. A replacement will be provided by libxpc.
Said replacement hasn't been provided yet to my knowledge, I checked the XPC framework's functions and objects.
I hope you understand my reasons behind having SMJobSubmit as the ideal and easiest solution here.
About
SMJobSubmit is "hard coding" the executable path, which means the user renaming your app (or any other manipulation) will both break your job and create an "opening" which could allow an attacker to "insert" their executable in place of your job.
I'm aware this can be a problem, but after all, SMJobSubmit is a launchd interface (its job CFDictionary is a launchd.plist AFAIK), and for launchd.plist-s Spawn Constraints have been introduced in macOS 14.0. My idea has been to include a Spawn Constraints key in the job plist according to Apple Documentation however I haven't gotten that far yet.
Also, it doesn't really matter whether the user renames the app I'm creating, since the executable to submit is inside the app bundle and I'm submitting a path computed by Bundle.path and co. I don't think it's possible for that to break, unless the user tampers with the bundle itself, which is protected in macOS by default with the App Management privacy feature, as far as I understood its purposes based on this WWDC video.
When I attempt to modify another app's bundle from Terminal for example, I get operation not permitted, unless Terminal was given App Management rights.
These above put confidence in me that SMJobSubmit can be used in a secure way. I wouldn't have started this project with SMJobSubmit if I hadn't been convinced that it's compatible with the security hardening interfaces macOS provides by its latest SDKs (environment/launch/spawn constraints, XPC connection validation, etc.)
I'll now go ahead and try your suggested debugging methods, thanks for the Profile especially, I wasn't aware this profile existed.
Thank you, Quinn. SMJobSubmit, even if deprecated, seems to be a routine aimed at this exact solution.
Also, Sparkle's solution as hinted by you also provides some nice ideas on how to get a more trustable authorization experience: https://github.com/sparkle-project/Sparkle/blob/2.x/InstallerLauncher/SUInstallerLauncher.m#L158.
Plus, even obtaining the right in it's most basic form (security authorize -u com.apple.ServiceManagement.daemons.modify) presents a more specialized dialog, "is trying to add a new helper tool" rather than "wants to make changes".
I'm also seeing sandboxed daemons behaving weirdly.
When calling
do {
try SMAppService.daemon(plistName: "com.example.daemon").register()
} catch let error {
[...]
}
the dialog in the right top corner saying Background Items Added and "Example App" added items that can run in the background for all users Do you want to allow this? appears.
Despite that, the register() method throws the
SMAppServiceDomain Code=1
error, which is operation not permitted.
Right after in the catch block, querying the .status of the daemon, I receive a value of 2, which corresponds to .requiresApproval.
I think this is a bug here, as the daemon's registration is successful, but the method still throws.