How to Whitelist Applications on macOS with the Parental Controls Payload
I recently went down the rabbit hole of trying to lock down a Mac so it could run a single application. On paper it sounded easy: just use Apple’s Parental Controls Application Access payload (com.apple.applicationaccess.new). My specific use case was trying to restrict macOS to only use Jamf's Self Service+ app.
What I Was Trying to Do
The goal was simple:
- Enable
familyControlsEnabled. - Add a
whiteListentry for Self Service+. - Deploy through Jamf and enjoy a kiosk-like setup where nothing else could run.
Where I Went Wrong
I built the payload using iMazing Profile Editor. It generated a plist which contained an appID field that looked like a nice chunk of base64 data. I figured, “Perfect, that’s what Apple wants.”
But here’s the catch: if you decode that base64, what you actually see is just the readable code requirement string:
anchor apple generic and identifier "com.jamf.selfserviceplus" ...
So the profile installed fine, but macOS wasn’t enforcing anything. Self Service+ wasn’t allowed, and other apps weren’t being blocked either. I had all the right pieces… but in the wrong format.
The Real Fix
After some digging (and a bit of trial and error), I realized that Apple’s docs are very specific:
appID Data: Required. The designated requirement describing the code signature of this executable. This value is obtained from the Security.framework using SecCodeCopyDesignatedRequirement.
That means macOS doesn’t want the readable string — it wants the compiled binary form of that requirement.
Here’s how I generated it:
# Extract the requirement text only (strip the Executable= line) 2>&1 \
codesign -d -r- -- "/Applications/Self Service+.app"| sed -n 's/^designated => //p' > req.txt# Compile it to binary
csreq -r req.txt -b req.bin# Base64 encode it for the profile < req.bin
base64
That gave me a new blob starting with +t4M....
When I dropped that into the appID field, suddenly everything clicked — Self Service+ opened fine, and other apps were blocked.
What the Final Payload Looks Like
Here’s the key piece of the working whitelist:
<key>whiteList</key><array> <dict> <key>bundleID</key> <string>com.jamf.selfserviceplus</string> <key>appID</key> <data>
+t4MAQAAANgAAAABAAAAAwAAABT63gwAAAAAxAAAAAEAAAAGAAAABgAAAA8A... </data> </dict></array>
What I Learned
- If your base64 decodes to readable text, it’s wrong.
- Use
csreq(orSecCodeCopyDesignatedRequirementin code) to get the compiled requirement. - Always verify with:
echo 'BASE64' | base64-D | csreq -r- -t
If you see the requirement string, you know it’s valid.
Final Thoughts
For me, once I switched from iMazing’s base64’d string to the actual compiled requirement, the whitelist behaved exactly as Apple describes.
I did submit a bug report to iMazing so hopefully they update their tool to avoid this issue in the future.
Comments ()