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 whiteList entry 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)
codesign -d -r- -- "/Applications/Self Service+.app"
2>&1 \
| sed -n 's/^designated => //p' > req.txt

# Compile it to binary
csreq -r req.txt -b req.bin

# Base64 encode it for the profile
base64
< req.bin

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 (or SecCodeCopyDesignatedRequirement in 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.