Thanks for being a part of WWDC25!

How did we do? We’d love to know your thoughts on this year’s conference. Take the survey here

Launch Constraint, SIP and legacy launchd plist

I have 2 basic questions related to Launch Constraints:

[Q1] Are Launch Constraints supposed to work when SIP is disabled?

From what I'm observing, when SIP is disabled, Launch Constraints (e.g. Launch Constraint Parent Process) are not enforced. I can understand that. But it's a bit confusing considering that the stack diagram in the WWDC 2023 session is placing the 'Environment Constraints' block under SIP, not above.

Also the documentation only mentions SIP for the 'is-sip-protected' fact.

[Q2] Is the SpawnConstraint key in legacy launchd plist files (i.e. inside /Library/Launch(Agents|Daemons)) officially supported?

From what I'm seeing, it seems to be working when SIP is enabled. But the WWDC session and the documentation don't really talk about this case.

Answered by DTS Engineer in 836594022
Are Launch Constraints supposed to work when SIP is disabled?

Your observations are inline with my expectations. In general, disabling SIP turns off modern security features like this.

I encourage you to file a bug against the documentation to request clarification here. Please post your bug number, just for the record.

Is the SpawnConstraint key in legacy launchd plist files … officially supported?

I see no mention of it in the launchd.plist man page, which is where I’d expect it to be documented.

But as a third-party developer I’m not sure that’s a significant restriction. If you’re building your own daemon or agent, you can bake spawn constraint into its code signature.

Share and Enjoy

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

Are Launch Constraints supposed to work when SIP is disabled?

Your observations are inline with my expectations. In general, disabling SIP turns off modern security features like this.

I encourage you to file a bug against the documentation to request clarification here. Please post your bug number, just for the record.

Is the SpawnConstraint key in legacy launchd plist files … officially supported?

I see no mention of it in the launchd.plist man page, which is where I’d expect it to be documented.

But as a third-party developer I’m not sure that’s a significant restriction. If you’re building your own daemon or agent, you can bake spawn constraint into its code signature.

Share and Enjoy

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

Feedback ticket for the documentation: FB17345983               

 

But as a third-party developer I’m not sure that’s a significant restriction. If you’re building your own daemon or agent, you can bake spawn constraint into its code signature.

This would protect the daemon or agent from being launched by an unexpected executable.

BUT this would not prevent the launchd plist from starting an executable at the path pointed by the plist but which is not the expected executable.

Thanks for filing FB17345983.

BUT this would not prevent the launchd plist from starting an executable at the path pointed by the plist but which is not the expected executable.

Sure, but what’s the actual threat there?

Most folks who install launchd property list files install the target executable in a directory that’s only writable by root. Given that, if someone can replace your executable they can just as easily modify your launchd property list file.

Share and Enjoy

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

Most folks who install launchd property list files install the target executable in a directory that’s only writable by root.

Because of what could be seen as a security regression introduced in macOS Installation framework some years ago, this can't be guaranteed.

this can't be guaranteed.

OK. But does that bug also affect /Library/LaunchDaemons? If so, protecting your tool doesn’t help.

Share and Enjoy

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

It's not specific to a location. But then there's the SIP factor and whether the default ownership and permissions are restrictive enough. Which is the case for /Library/LaunchDaemons.

So the issue I'm concerned about is not with the launchd plist file but really with the program targeted by the plist.

Sorry I didn’t respond earlier. I didn’t see your reply because it was in a comment. See tip 5 in Quinn’s Top Ten DevForums Tips.

I'm concerned about … the program targeted by the plist.

Sure. My advice in that case is to install the program in a directory that’s only writable by root [1]. Is there some reason you’re unable to do that?

Share and Enjoy

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

[1] Well, not just that directory but all directories on the path. But that holds for the two most common locations for daemons, namely, somewhere within /usr/local and somewhere within /Library/Application Support.

Is there some reason you’re unable to do that?

Yes, it's related to other macOS requirements that make it mandatory to have the binary in this location (whose parent system directories are not root:wheel 755).

other macOS requirements that make it mandatory to have the binary in this location

What location is that? /Applications?

Share and Enjoy

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

A sub folder of /Applications, yes.

A sub folder of /Applications, yes.

A subfolder? Hmmm. What part of the system requires you to put your app in a subfolder of the Applications folder?

Share and Enjoy

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

Launch Constraint, SIP and legacy launchd plist
 
 
Q