When a managed Mac behaves like an app has lost its mind, I try to prove the privacy profile before I blame the app.
That sounds dramatic, but it is usually a normal support ticket. Zoom opens, but the user cannot share their screen. A backup client is installed, but it cannot see the files that actually need to be backed up. An automation tool works on my test Mac, then fails on a user’s machine because macOS blocks access to another app, a protected folder, or a system service.
That is where Privacy Preferences Policy Control comes in. PPPC is the configuration profile payload macOS uses to manage many of the privacy controls that live under Privacy & Security. Apple documents the payload as com.apple.TCC.configuration-profile-policy, and the important operational detail is that if more than one PPPC payload is present, macOS uses the more restrictive settings. Apple’s PPPC payload documentation
That last detail is why I do not start by assuming the app is broken. I want to know what the Mac is enforcing.
The Two Examples I Actually Care About
There are two examples I run into enough that they are worth separating.
The first is Zoom screen sharing. Users expect Zoom to share the screen because that is the whole point of the meeting. The security model is different from a lot of other PPPC services, though. Apple does not let an admin silently grant Screen Recording access for an app the same way we can grant some other privacy permissions. What we can do is allow a standard user to approve Screen Recording without needing admin credentials.
That is the correct security tradeoff. Screen Recording is not a small permission. It lets an app read the contents of the display. I do not want an MDM profile quietly giving every conferencing app that access forever. I want the user to make the final approval when the app asks, and I want the admin workflow to remove the unnecessary admin-password roadblock.
The second example is Backblaze Full Disk Access. A backup tool that cannot read protected user data is not really a backup tool. For that use case, I do want PPPC to grant the right access because the purpose of the software is to read files broadly enough to protect the Mac. Apple lists System Policy All Files as the PPPC service that allows specified apps access to protected data like Mail, Messages, Safari, Home, Time Machine backups, and certain administrative settings for all users of the Mac. Apple’s PPPC payload documentation
Those two examples are the whole point of the post. PPPC is not one generic “allow the app” switch. Zoom and Backblaze need different decisions because they touch different parts of macOS privacy.
Path 1: Build the Plist by Hand
I do not usually want hand-built PPPC profiles to be the long-term workflow, but I do want to understand the plist. If I cannot read the payload, I am depending entirely on the UI to tell me what I deployed.
For Zoom, I am targeting the app bundle identifier us.zoom.xos. On my Mac, the designated requirement for the installed Zoom app is:
identifier "us.zoom.xos" and anchor apple generic and certificate 1[field.1.2.840.113635.100.6.2.6] /* exists */ and certificate leaf[field.1.2.840.113635.100.6.1.13] /* exists */ and certificate leaf[subject.OU] = BJ4HAAB9B3
I would still verify that on the Mac where I am building the profile:
codesign -dr - /Applications/zoom.us.app 2>&1
For Screen Recording, the part I care about is the Authorization value. I am not trying to silently approve screen capture. I am allowing a standard user to approve it.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>PayloadContent</key>
<array>
<dict>
<key>PayloadType</key>
<string>com.apple.TCC.configuration-profile-policy</string>
<key>PayloadIdentifier</key>
<string>org.jonbrown.pppc.zoom.screenrecording</string>
<key>PayloadUUID</key>
<string>BFC43791-6E92-43C3-BE6A-B040C12F4A39</string>
<key>PayloadVersion</key>
<integer>1</integer>
<key>PayloadDisplayName</key>
<string>PPPC Zoom Screen Recording</string>
<key>Services</key>
<dict>
<key>ScreenCapture</key>
<array>
<dict>
<key>Identifier</key>
<string>us.zoom.xos</string>
<key>IdentifierType</key>
<string>bundleID</string>
<key>CodeRequirement</key>
<string>identifier "us.zoom.xos" and anchor apple generic and certificate 1[field.1.2.840.113635.100.6.2.6] /* exists */ and certificate leaf[field.1.2.840.113635.100.6.1.13] /* exists */ and certificate leaf[subject.OU] = BJ4HAAB9B3</string>
<key>Authorization</key>
<string>AllowStandardUserToSetSystemService</string>
<key>Comment</key>
<string>Allow standard users to approve Zoom screen sharing without admin credentials.</string>
</dict>
</array>
</dict>
</dict>
</array>
<key>PayloadType</key>
<string>Configuration</string>
<key>PayloadVersion</key>
<integer>1</integer>
<key>PayloadIdentifier</key>
<string>org.jonbrown.pppc.zoom</string>
<key>PayloadUUID</key>
<string>B3F76C2A-B38D-443C-8E71-186340D668EB</string>
<key>PayloadDisplayName</key>
<string>Zoom Screen Recording PPPC</string>
<key>PayloadScope</key>
<string>System</string>
</dict>
</plist>
After that profile lands, the user still has work to do. They open Zoom, start a screen share, and macOS prompts them to enable Screen Recording. The user goes to System Settings > Privacy & Security > Screen & System Audio Recording, enables Zoom, and then quits and reopens Zoom when macOS asks. The profile removes the admin-rights problem. It does not remove the consent step.
Backblaze is different. The profile needs to grant Full Disk Access. I would still build and test this from the installed Backblaze client, but I would not start from a blank page anymore. Backblaze has an RMM repository with Jamf-specific reference material, including a jamf/profiles path Jon pointed me to for PPPC/profile examples. The top-level repo describes the Jamf implementation as a reference implementation for deploying, monitoring, and managing Backblaze Computer Backup at scale, with silent install, bzcli operations, extension attributes, optional smart groups, and staged validation. Backblaze RMM integration Backblaze Jamf profiles
That matters because Backblaze is not just an app icon sitting in /Applications. A backup product can include helper processes, menu components, command-line tooling, and management automation. Backblaze’s published Jamf profiles include one Full Disk Access profile for com.backblaze.Backblaze and another for com.backblaze.bzbmenu. That tells me I should think about the backup client and menu/helper component separately instead of assuming one visible app bundle is the whole story.
This is the Backblaze Full Disk Access profile from their Jamf profile reference:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>PayloadContent</key>
<array>
<dict>
<key>PayloadType</key>
<string>com.apple.TCC.configuration-profile-policy</string>
<key>PayloadVersion</key>
<integer>1</integer>
<key>PayloadIdentifier</key>
<string>com.backblaze.pppc.backblaze</string>
<key>PayloadUUID</key>
<string>9A0A3F2B-1111-4444-8888-BACKBLAZE01</string>
<key>PayloadDisplayName</key>
<string>PPPC Backblaze Full Disk Access</string>
<key>Services</key>
<dict>
<key>SystemPolicyAllFiles</key>
<array>
<dict>
<key>Identifier</key>
<string>com.backblaze.Backblaze</string>
<key>IdentifierType</key>
<string>bundleID</string>
<key>CodeRequirement</key>
<string>anchor apple generic</string>
<key>Allowed</key>
<true/>
</dict>
</array>
</dict>
</dict>
</array>
<key>PayloadType</key>
<string>Configuration</string>
<key>PayloadIdentifier</key>
<string>com.backblaze.pppc.root</string>
<key>PayloadVersion</key>
<integer>1</integer>
<key>PayloadUUID</key>
<string>9A0A3F2B-ROOT-4444-8888-BACKBLAZE</string>
<key>PayloadDisplayName</key>
<string>Backblaze PPPC</string>
<key>PayloadScope</key>
<string>System</string>
</dict>
</plist>
And this is the companion Full Disk Access profile Backblaze publishes for bzbmenu:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>PayloadContent</key>
<array>
<dict>
<key>PayloadType</key>
<string>com.apple.TCC.configuration-profile-policy</string>
<key>PayloadVersion</key>
<integer>1</integer>
<key>PayloadIdentifier</key>
<string>com.backblaze.pppc.bzbmenu</string>
<key>PayloadUUID</key>
<string>9A0A3F2B-2222-4444-8888-BZBMENU01</string>
<key>PayloadDisplayName</key>
<string>PPPC bzbmenu Full Disk Access</string>
<key>Services</key>
<dict>
<key>SystemPolicyAllFiles</key>
<array>
<dict>
<key>Identifier</key>
<string>com.backblaze.bzbmenu</string>
<key>IdentifierType</key>
<string>bundleID</string>
<key>CodeRequirement</key>
<string>identifier "com.backblaze.bzbmenu" and anchor apple generic</string>
<key>Allowed</key>
<true/>
</dict>
</array>
</dict>
</dict>
</array>
<key>PayloadType</key>
<string>Configuration</string>
<key>PayloadIdentifier</key>
<string>com.backblaze.pppc.bzbmenu.root</string>
<key>PayloadVersion</key>
<integer>1</integer>
<key>PayloadUUID</key>
<string>9A0A3F2B-ROOT-4444-8888-BZBMENU</string>
<key>PayloadDisplayName</key>
<string>Backblaze bzbmenu PPPC</string>
<key>PayloadScope</key>
<string>System</string>
</dict>
</plist>
The values are not busywork. They are the boundary. On the test Mac, I would still install the same Backblaze build I plan to deploy, identify the app or helper that needs Full Disk Access, and pull the code requirement from that exact binary.
codesign -dr - /path/to/Backblaze.app 2>&1
codesign -dr - /path/to/backblaze/helper/or/binary 2>&1
If the backup engine is a helper outside the main app bundle, I want the helper in the profile. If the main app is the only target, I want the bundle ID. Backblaze’s own Jamf examples give me a better starting point than guessing, but I still want a test Mac to prove the profile matches the version I am deploying. What I do not want is a copied profile from an old deployment that grants access to the wrong binary and then leaves me wondering why backups are incomplete.
Path 2: Use PPPC Utility
The reason I still recommend Jamf’s PPPC Utility is that it shortens the distance between the app on disk and the profile I need in Jamf. Jamf describes it as a macOS app for creating configuration profiles that contain the PPPC payload. The current README says profiles can be saved locally, signed or unsigned, and uploaded directly to a Jamf Pro server. It also notes that you start by adding bundles or executables with drag-and-drop or the add button. Jamf PPPC Utility
That is exactly the workflow I want for these two examples.
For Zoom, I would open PPPC Utility, add /Applications/zoom.us.app, select Screen Recording, and set the authorization so a standard user can approve the permission. I would save the profile, upload it into Jamf Pro, scope it to a test Mac, and then walk through the user approval flow. If the user can approve Screen Recording without admin credentials, the profile is doing what I wanted.
For Backblaze, I would look at Backblaze’s Jamf profile reference first, then install Backblaze on a test Mac and use PPPC Utility against the actual app or helper that needs Full Disk Access. I would set System Policy All Files to Allow, save the profile, upload it into Jamf Pro, and test a real backup path that includes protected user data.
Jamf’s support article keeps the basic flow simple: download PPPC Utility, add the app, customize the allowance settings, save the profile, upload the .mobileconfig in Computers > Configuration Profiles, check the selected values, scope it to a test computer, and save. Configuring Privacy Preferences Policy Control with PPPC Utility
The upside of PPPC Utility is speed and accuracy. It can pull the app identity from the local Mac, which is usually where people make mistakes when they hand-build these profiles. The downside is that it can also make it easy to click through without understanding what the profile says. I still open the saved mobileconfig and read the Services section before I treat it as production-ready.
Path 3: Build It Natively in Jamf Pro
The third path is Jamf Pro itself. I use this when I want the profile to be born in Jamf instead of imported from a file.
The workflow is straightforward. In Jamf Pro, go to Computers > Configuration Profiles, create a new macOS configuration profile, and add the Privacy Preferences Policy Control payload. From there, add the application or path, choose the identifier type, enter the bundle ID or file path, paste the code requirement, select the service, and choose the authorization.
For Zoom, the native Jamf payload should describe Screen Recording for us.zoom.xos with user-approved enablement. The practical test is not whether the profile exists in Jamf. The practical test is whether a standard user can approve Zoom screen sharing without an admin prompt.
For Backblaze, the native Jamf payload should describe System Policy All Files for the Backblaze app or helper that actually reads user data. The practical test is whether Backblaze can back up protected locations after the profile installs, not whether the app merely launches.
The advantage of the native Jamf path is operational cleanliness. The profile lives where the scope, exclusions, smart groups, and change history live. The downside is that you need to bring the app identity and code requirement with you. If those values are wrong, Jamf will happily deploy a profile that looks complete and does not solve the problem.
All Roads End in Jamf
I do not care which path starts the profile as long as the final deployment is controlled in Jamf.
Manual plist work is useful when I need to understand or troubleshoot the payload. PPPC Utility is useful when I want to generate a profile from the actual installed app and avoid hand-copying code requirements. Jamf Pro’s native PPPC payload is useful when I want the whole workflow to stay inside the management system.
All three paths still end the same way for me:
- Build the profile from the actual app or helper.
- Verify the bundle ID, path, service, authorization, and code requirement.
- Scope it to a test Mac.
- Confirm the user experience.
- Search Jamf for overlapping PPPC profiles before broad deployment.
- Scope production in a controlled group, not the entire fleet on the first save.
That last step matters because Apple is explicit that multiple PPPC payloads can exist and the more restrictive settings win. If Zoom still cannot share the screen, or Backblaze still cannot read protected files, I want to know whether I deployed the wrong payload, scoped the wrong computer, targeted the wrong binary, or collided with another profile.
PPPC is not just a way to make prompts disappear. It is a way to make privacy decisions explicit. For Zoom, that means letting the user approve screen sharing without needing admin rights. For Backblaze, that means granting Full Disk Access to the component that actually needs to protect the Mac. In both cases, the profile should explain the decision clearly enough that another admin can open it six months later and understand why it exists.
Sources
- Apple Privacy Preferences Policy Control payload documentation
- Apple PPPC custom payload examples
- Jamf PPPC Utility
- Configuring Privacy Preferences Policy Control with PPPC Utility
- PPPC Utility notes and examples
- Backblaze RMM integration
- Backblaze Jamf profiles
AI Usage Transparency Report
AI Era · Written during widespread use of AI tools
AI Signal Composition
Score: 0.33 · Moderate AI Influence
Summary
Privacy Preferences Policy Control (PPPC) is a configuration profile payload used by macOS to manage privacy controls. It's not a single 'allow the app' switch, but rather a nuanced approach that requires careful consideration of each app's specific needs and permissions.
Related Posts
Ranking Jamf Extension Attributes by Smart Group Usage
I built a read-only Python script for Jamf Pro that ranks computer extension attributes by how often they are referenced in Smart Computer Groups and writes JSON and HTML reports for review.
WWDC 2026 Was Bigger Than The Keynote
Most of those conversations eventually landed in the same place. Siri wasn't ready. Liquid Glass was everywhere. There was no new hardware announcement. Depending on who you asked, WWDC 2026 was either disappointing or forgettable.
ABM Warranty 0.5.1
ABM Warranty 0.5.1 adds outbound connection workflows for JAMF and OAuth-based APIs, an expanded device detail view, outbound job tracking, and guide updates for connection setup and sync review.
ABM Warranty 0.5.0
ABM Warranty 0.5.0 expands the platform with tenant-aware desktop widgets and notifications, giving teams clear, real-time visibility into fleet health, expiring coverage, and devices requiring attention across ABM/ASM environments. This release introduces a powerful CLI for managing notifications and sync workflows, alongside a new job-based architecture with chunking, sync history tracking, and an enterprise sync mode designed to scale with large device fleets. Additional enhancements include API credential rotation for security-conscious organizations, notification muting for known exceptions, forward-compatible database migration paths, and full localization support across 10 languages for global...
Discovering Mole: A Command Line Utility for Mac Cleaning
Caches pile up, apps leave behind junk, and disk space slowly disappears. While there are plenty of GUI tools out there, most of them either lack transparency or feel overly bloated.
Automating JAMF Pro Email Notifications with SendGrid (Smart Group Driven Workflows)
Modern device management isn't just about enforcing policies—it's about communicating effectively with users at the right time. In JAMF Pro, Smart Groups give you powerful visibility into device state, but they don't natively solve the problem of proactive, automated user communication. Whether you're trying to prompt users to restart their machines, complete updates, or take action on compliance issues, bridging that gap requires a flexible and scalable notification system.
Introducing Pique - The Game-Changing Quick Look Plugin for Mac Admins
As a Mac admin, I'm always on the lookout for tools that make my life easier and more efficient. Recently, I stumbled upon Pique - a brilliant Quick Look plugin created by Henry Stamerjohann that allows you to view file contents in a syntax highlighted way.
ABM Warranty 0.4.1 Walkthrough: Wrap-Up and Beta
In this final ABM Warranty 0.4.1 walkthrough, I’m wrapping up the last features I had not covered directly in the earlier videos and then focusing on support, community, and the beta program. I also want to show where the support resources live inside the app so you know where to go if you need help, documentation, or a way to send useful feedback. Additionally, I'll be covering some of the key features that were updated since the previous version, including any bug fixes or improvements made to existing functionality.
ABM Warranty 0.4.1 Walkthrough: Managed Preferences
In this part of the ABM Warranty 0.4.1 walkthrough series, I'm focusing on managed preferences and the credential packaging workflow. In the last video, I covered multiple credentials inside the app itself. In this one, I'm showing how to package those credentials so they can be deployed securely through MDM. This process is a crucial step in ensuring that your credentials are properly configured and protected within your organization's mobile device management system.