When Monday Morning Gets Interesting
Imagine this: you're sipping coffee on a calm Monday morning when suddenly Microsoft's new directive hits your inbox. Now you're scrambling to ensure no rogue AD writer hijacks your precious Entra roles. Don't panic—grab your PowerShell cape, and let's save your directory from impending doom.
Deadline Alert: Effective June 1, 2026, Microsoft will block hard-matching new Active Directory user objects to existing cloud users that hold an Entra role. If you run hybrid identity with Entra Connect or Cloud Sync, keep reading.
SyncJacking 101: What Is It?
Microsoft is tightening hybrid identity practices—and for a good reason. SyncJacking is a potential attack where an adversary with Active Directory write access could craft an on-premises user object that hard-matches to a privileged cloud account through Entra Connect synchronization.
In plain English: an attacker who can create or modify AD user objects could inject their account into your cloud directory, hijacking a privileged Entra account faster than you can say "Zero Trust." Not so funny when your Global Admin account suddenly starts offering free crypto on LinkedIn.
How It Works
- Attacker gains write access to on-premises Active Directory.
- Creates a new AD user with a
mS-DS-ConsistencyGuid(ImmutableID) that matches a privileged cloud-only Entra user. - Entra Connect syncs the object and hard-matches it to the existing cloud user.
- The attacker now controls the on-premises copy—and by extension, the privileged cloud account.
The fix: Microsoft's upcoming enforcement will block hard-matching for any cloud user that holds an Entra directory role, effectively shutting down this attack vector.
The Problem: Are You Already Exposed?
Before June 1 rolls around, you need to answer one critical question: do any of your Entra role holders have an onPremisesImmutableId set?
If they do, those accounts are synced from (or have been matched to) on-premises AD. That's exactly the scenario Microsoft is locking down. You need to audit both:
- Permanently assigned roles — Users with always-on directory role assignments.
- PIM-eligible roles — Users who can activate privileged roles through Privileged Identity Management.
Why both? The basic audit script from the original advisory only covers permanent assignments. PIM-eligible users are equally at risk—if someone can activate Global Admin, they're a target for SyncJacking too.
Script 1: Audit Permanent Role Assignments
Let's tackle the straightforward case first—accounts with permanently assigned Entra directory roles:
Required Graph Scopes (Delegated)
Directory.Read.All— read user properties includingonPremisesImmutableIdRoleManagement.Read.Directory— read Entra directory role assignments
# Connect to Microsoft Graph API (delegated / interactive)
Connect-MgGraph -Scopes "Directory.Read.All", "RoleManagement.Read.Directory"
# Query all permanent role assignments and check for synced accounts
Get-MgRoleManagementDirectoryRoleAssignment -All | ForEach-Object {
$user = Get-MgUser -UserId $_.PrincipalId `
-Property "displayName,userPrincipalName,onPremisesImmutableId,onPremisesSyncEnabled" `
-ErrorAction SilentlyContinue
if ($user -and $user.onPremisesImmutableId) {
[PSCustomObject]@{
Name = $user.displayName
UPN = $user.userPrincipalName
ImmutableId = $user.onPremisesImmutableId
SyncEnabled = $user.onPremisesSyncEnabled
}
}
} | Format-Table -AutoSize
Reading the output: No output means you're in the clear. Any results mean those synced accounts hold permanent Entra roles—investigate and remediate before June 1.
Script 2: Audit PIM-Eligible Assignments
Because why settle for 70% safety when you can have 100%? PIM-eligible roles are the gap most admins miss. If someone can activate Global Admin through PIM, they're just as much a SyncJacking target.
Required Graph Scopes (Delegated)
RoleEligibilitySchedule.Read.Directory— read PIM eligibility schedulesDirectory.Read.All— read user properties
Why RoleEligibilitySchedule and not RoleAssignmentSchedule? The AssignmentSchedule cmdlet returns active assignments (which overlap with Script 1). The EligibilitySchedule cmdlet returns users who are eligible to activate a role through PIM but haven't activated it yet—that's the gap we need to close.
# Connect to Microsoft Graph API with PIM eligibility scopes
Connect-MgGraph -Scopes "RoleEligibilitySchedule.Read.Directory", "Directory.Read.All"
# Query all PIM-eligible role schedules (users who CAN activate a role)
$schedules = Get-MgRoleManagementDirectoryRoleEligibilitySchedule -All
$results = foreach ($schedule in $schedules) {
$user = Get-MgUser -UserId $schedule.PrincipalId `
-Property "displayName,userPrincipalName,onPremisesImmutableId,onPremisesSyncEnabled" `
-ErrorAction SilentlyContinue
if ($user -and $user.onPremisesImmutableId) {
[PSCustomObject]@{
Name = $user.displayName
UPN = $user.userPrincipalName
ImmutableId = $user.onPremisesImmutableId
Role = $schedule.RoleDefinitionId
SyncEnabled = $user.onPremisesSyncEnabled
}
}
}
# Display in console
$results | Format-Table -AutoSize
# Export to CSV for audit trail
$results | Export-Csv -Path "PIM_Affected_Users.csv" -NoTypeInformation
Pro Tip: Resolve Friendly Role Names
The RoleDefinitionId output is a GUID. To get a human-readable role name, you can look it up with Get-MgRoleManagementDirectoryRoleDefinition and match on Id. Here's a quick snippet to replace the GUID with the display name:
# Fetch all role definitions for name lookup
$roleDefs = Get-MgRoleManagementDirectoryRoleDefinition -All
# Then in your output, replace:
# Role = $schedule.RoleDefinitionId
# With:
# Role = ($roleDefs | Where-Object { $_.Id -eq $schedule.RoleDefinitionId }).DisplayName
CSV glory: The script exports results to PIM_Affected_Users.csv—making audit reviews easier than remembering your cat's vaccination calendar.
Interpreting Your Results
No Output
You're clean. None of your Entra role holders are synced from on-prem AD. No action needed—enjoy your coffee.
Results Returned
These accounts have both an Entra role and an onPremisesImmutableId. Investigate each one before the June 1 deadline.
Remediation Options
- Convert to cloud-only: If the account doesn't need to sync, remove the
onPremisesImmutableIdby moving it out of sync scope and converting it to a cloud-only account. - Remove the Entra role: If the account is legitimately synced and doesn't need the privileged role, remove the role assignment.
- Use a dedicated cloud-only admin account: Best practice is to have privileged Entra roles assigned to cloud-only accounts, separate from synced identities.
- Review PIM eligibility: Ensure PIM-eligible users are intentional and documented. Remove stale eligibility assignments.
Technical Notes
Things to Keep in Mind
- Scopes are requested in-script: Each script's
Connect-MgGraph -Scopesline already requests exactly the delegated permissions it needs. You'll be prompted for consent on first run if your app registration hasn't pre-consented them. - Admin consent may be required:
Directory.Read.All,RoleManagement.Read.Directory, andRoleEligibilitySchedule.Read.Directorytypically require tenant admin consent. If you're not a Global Admin, ask one to grant consent first. - API throttling: For large directories, the Graph API may throttle requests. The
-Allparameter handles pagination automatically, but if you have thousands of role assignments, expect the script to take a few minutes. - Service principals vs users: The
PrincipalIdon a role assignment can be a user, group, or service principal. The scripts use-ErrorAction SilentlyContinueto gracefully skip non-user principals. - Module requirements: You'll need
Microsoft.Graph.Authentication,Microsoft.Graph.Users, andMicrosoft.Graph.Identity.Governance. See install commands below.
Install the Required Modules
# Option A: Install the full Microsoft Graph SDK (all submodules)
Install-Module Microsoft.Graph -Scope CurrentUser
# Option B: Install only the submodules these scripts need
Install-Module Microsoft.Graph.Authentication -Scope CurrentUser
Install-Module Microsoft.Graph.Users -Scope CurrentUser
Install-Module Microsoft.Graph.Identity.Governance -Scope CurrentUser
Wrap-Up: Protect Your Hybrid Identity
By running both scripts, you're not just protecting your Active Directory—you're ensuring no sync-enabled supervillain can hijack your infrastructure. Do it for your users. Do it for the compliance team. Do it for lunch breaks uninterrupted by a SOC email titled "Privileged Account Anomaly."
Your Action Checklist
- Run Script 1 to audit permanent Entra role assignments.
- Run Script 2 to catch PIM-eligible assignments.
- Investigate any accounts that appear in the results.
- Remediate before June 1, 2026.
- Consider adopting the best practice of using cloud-only admin accounts for privileged Entra roles.
Remember: the best time to audit your hybrid identity was yesterday. The second-best time is right now. Fire up that PowerShell console and let's keep your cloud fortress secure.
Stay safe out there, cloud ninjas.