PatchDayAlert
Field Note · 7 min read · 1,375 words By Colten Anderson · Field Notes

Two profiles, one setting: how to catch the MDM overlap that makes enforcement random

When two configuration profiles set the same value on one device, macOS and Intune stop enforcing it deterministically. Here are the detection commands and reports that find the overlap before it burns you.

Two profiles, one setting: how to catch the MDM overlap that makes enforcement random

You set a firewall or FileVault value in your MDM, watched it save, and moved on. Weeks later a spot check shows it isn’t applied on a handful of Macs. You re-push it. It applies. Next morning it’s gone again. Nothing in the console explains it, because as far as the console is concerned the profile deployed cleanly.

That intermittent, un-loggable flapping is the fingerprint of two profiles setting the same value on one device. When it happens, the OS doesn’t throw an error and it doesn’t quietly prefer the newer profile. It picks one, seemingly at random, and the choice can flip on the next check-in. A setting you thought you owned is now a coin toss, and the coin is not in your hand.

This installment of Checks you can run today is the detection side: the commands and reports that surface an overlap on macOS and in Intune before it turns into a help desk queue you can’t explain.

How the overlap actually happens

Two different setups produce the same symptom.

One tenant, two Intune policies. You have a settings-catalog profile that sets a value, and a second policy, maybe an endpoint-security baseline, that sets the same value differently. Both target the same device. Intune doesn’t merge them and it doesn’t pick a winner. It flags the setting and stops.

One Mac, two profile sources. Apple only lets a Mac hold one MDM enrollment at a time, so you can’t stack Intune on top of Jamf or Kandji. You can’t install one MDM profile on top of another. The overlap that bites you is quieter than a second MDM. It’s a .mobileconfig someone double-clicked. It’s a leftover management profile from an MDM migration where the old profile was never removed off the device. It’s two profiles inside the same MDM that both carry the same payload, which is the Jamf case Alan Siu documented: a full templated profile sitting next to a custom XML upload that touches the same keys.

The macOS case is the meaner one, because Apple’s own guidance is blunt about the result: “If you have multiple configuration profiles containing the same payloads with different settings, the resulting behavior is undefined.” A few security-sensitive payloads resolve to the most restrictive value across all installed profiles, but that is the exception. For most settings, undefined means undefined.

macOS: enumerate every profile on the device

The profiles command lists what’s actually installed, independent of what any MDM thinks it pushed. Run these on the host.

# Profiles installed for the current user
profiles list

# As root, dump every profile on the device to the console as an XML plist
sudo profiles show -output stdout

# Show the MDM / DEP enrollment profile specifically
sudo profiles show -type enrollment

Note that on macOS 11 and later the tool can no longer install profiles, only read them. That’s fine here; reading is the whole job.

  • Bad: the same payload type shows up under more than one profile, or a leftover profile from a prior MDM is still enrolled alongside your current one. Both mean the OS has more than one answer for the same setting.
  • Good: one profile per payload, all traceable to your current management source.
  • Fix: remove the extra. A hand-installed profile comes off in System Settings > General > Device Management (older builds: System Preferences > Profiles), or with sudo profiles remove. Then deliver the setting from one source only.

To flag duplicates instead of reading the whole plist by eye, count how many profiles declare each payload type:

sudo profiles show -output stdout > /tmp/profiles.plist
grep -A1 '<key>PayloadType</key>' /tmp/profiles.plist \
  | grep '<string>' | sort | uniq -c | sort -rn

Any payload type with a count above 1 is worth opening. This is a first pass, not proof: two profiles can legitimately carry the same payload type for unrelated settings. But it points you at the profiles to compare, which beats guessing. The tell Siu named is the behavioral one, a setting that “is enforced, and then isn’t, and then is.” If a value flaps like that, this is where the flap lives.

Intune: the per-setting status report names the collision

Intune won’t make you diff plists. It reports the conflict directly, in two places.

First, the setting-level view. Go to Devices > Manage devices > Configuration, open the policy, and under Device and user check-in status select Per setting status. Each setting carries its own state, and the one you want is Conflict: “Two settings are applied to the same device, and Intune can’t sort out the conflict.”

Second, the device-level view that names which policies collide. Go to Devices > All devices, pick the device, open Device configuration, and select the policy showing a Conflict state. Selecting the conflict row opens a window that lists every policy and profile name carrying the setting that’s fighting. That is the piece you need, because knowing a setting conflicts is useless until you know the two policies to reconcile.

  • Bad: any setting sits in Conflict. Per Microsoft, that’s either “an existing setting on the device that Intune can’t override” or “two policies with the same setting using different values.” Either way the value on the device is not the one you meant to enforce.
  • Good: the per-setting report is clean, and each setting traces to exactly one policy.
  • Fix: open the conflict row, read off the two policies, and decide which one owns the setting. Then remove it from the other, or fix the scoping so both never land on the same device.

The overlap map

Conflict sourceHow to detectHow it resolvesFix
Two Intune policies set the same setting (one tenant)Per-setting status shows Conflict; the device’s Device configuration conflict row lists both profiles by nameIntune “can’t sort out the conflict” and stops; the value you intended is not reliably appliedConsolidate into one policy, or scope assignments and exclusions so only one policy reaches the device
macOS: same payload from a live MDM plus a leftover or hand-installed profilesudo profiles show -output stdout; System Settings > Device ManagementApple: “the resulting behavior is undefined” (a few security payloads take the most restrictive value)Remove the leftover or manual profile; deliver the setting from one source
Jamf: full/templated profile overlapping a custom-XML upload of the same payloadprofiles list on the host, cross-checked against Jamf’s profile list; the intermittent-enforcement symptomEnforced “seemingly randomly” per check-inDon’t mix a templated profile and a custom upload for the same payload; pick one and delete the other

The resolution path: one setting, one source

Detection is most of the battle, but the fix has an order to it.

Consolidate first. If two profiles both need to exist for other reasons, move the contested setting into exactly one of them and strip it out of the other. Two profiles can coexist all day as long as they don’t both claim the same payload.

Then fix scoping so the overlap can’t come back. Most Intune conflicts are an assignment problem wearing a settings costume: a broad group and a narrower group both catch the same machines. Target the policy that should win to the population that should have it, and use an exclusion group to carve that population out of the competing policy. On macOS, the equivalent discipline is process, not tooling: when you migrate MDMs, send the removal command from the old MDM first so you aren’t leaving orphaned profiles behind to fight the new ones.

This is a cousin of the Intune device that passes Conditional Access without ever being checked. That one is a device no policy touches. This one is a device two policies touch at once. Both end the same way: the tenant reports success while the control you care about never deterministically runs.

The boring version works. Find the second profile, kill it, and confirm the payload comes from one place. Enforcement only stops being a coin flip when there’s a single answer to flip to.

Sources

Share

Related field notes

Get the free CVE triage cheat sheet

Subscribe and we'll email you the one-page triage flow for fresh CVEs. Plus the weekly digest.

Subscribe