Background
Azure RBAC has over 800 built-in roles. Most of them are scoped to specific services and grant only the permissions needed for that specific service. Many of the built-in roles are classified as privileged by Microsoft. Which means they are intentionally broad in their permissions and need to be properly protected, like gated behind PIM approval workflows, monitoring etc, making sure access to them is short-lived and so on. But sometimes these RBAC roles ship with permissions that are broader than their name and description suggests.
This isn't a new problem. During fwd:cloudsec Europe 2025 in Berlin, Ariel Simon at Token Security published research showing several built-in roles containing an unnecessary */read permission, effectively giving every user assigned those roles full Reader access across the entire subscription.
The Approach
Nothing fancy. I wrote a PowerShell script that pulls every built-in Azure role definition and filters for actions containing what I consider potentially "dangerous" keywords:
$roles = Get-AzRoleDefinition | Where-Object { $_.IsCustom -eq $false }
$results = @()
foreach ($role in $roles) {
$actions = $role.Actions
if ($actions -match '(write|delete|update|create|manage|allTasks)' -or $actions -contains '*') {
$results += [PSCustomObject]@{
RoleName = $role.Name
Id = $role.Id
Description = $role.Description
Actions = $role.Actions
}
}
}
$results | ConvertTo-Json -Depth 3This gave me a list of every built-in role with some form of write or destructive capability. Most of them are expected like User Access Administrator, Owner and various other admin roles. But one stood out almost immediately.
The Finding
The Azure IoT Operations Onboarding role (ID: 7b7c71ed-33fa-4ed2-a91a-e56d5da260b5) had the following in its actions:
Microsoft.Authorization/*/writeThis wildcard grants write access to the entire Microsoft.Authorization resource provider, which includes role assignments, role definitions, deny assignments and locks. Anyone with this role can create role assignments including assigning themselves Owner, User Access Administrator or any other role at the scope where the IoT Onboarding role was assigned.
The full permission list from the role definition:
"actions": [
"Microsoft.IoTOperations/*",
"Microsoft.DeviceRegistry/register/action",
"Microsoft.DeviceRegistry/schemaRegistries/read",
"Microsoft.DeviceRegistry/schemaRegistries/write",
"Microsoft.Authorization/*/read",
"Microsoft.Authorization/*/write",
"Microsoft.Insights/alertRules/*",
"Microsoft.Resources/deployments/*",
"Microsoft.Resources/subscriptions/resourceGroups/read",
"Microsoft.Edge/sites/read"
]The role description says: "User can Azure arc connect and deploy Azure IoT Operations securely". However, there is no mention of granting RBAC roles to anyone.
Does it matter?
Yes, it does. The Microsoft.Authorization/*/write permission grants full control over RBAC at the assigned scope. This means any user with this role can assign themselves Owner or any other role. Unlike Owner or User Access Administrator, this role is not classified as privileged by Microsoft. That matters because:
- Organizations using Privileged Identity Management (PIM) usually rely on privileged tags to know what roles to protect.
- Access reviews targeting privileged roles won't flag this.
- Conditional Access policies scoped to privileged role activation won't apply.
- An admin assigning this role to a user or service principal has no indication that they're granting what amounts to full control based on the role's description.
Reproduction
The privilege escalation is straightforward.
Step 1. Assign the Azure IoT Operations Onboarding role to a user at any scope:
az role assignment create \
--assignee <user-object-id> \
--role "7b7c71ed-33fa-4ed2-a91a-e56d5da260b5" \
--scope /Step 2. Authenticate as that user and assign yourself Owner at the same (or child) scope:
az role assignment create \
--assignee <user-object-id> \
--role "Owner" \
--scope /subscriptions/<subscription-id>In my PoC submitted to MSRC, I demonstrated this at the tenant root scope, which can give Owner access to every subscription in the tenant.
The Fix
Microsoft fixed the role by making two changes:
- Scoping down the wildcard.
Microsoft.Authorization/*/writewas replaced withMicrosoft.Authorization/roleAssignments/write, removing the ability to create or modify role definitions, deny assignments and locks. - Adding an ABAC condition. The remaining
roleAssignments/writepermission is now constrained by a condition which only allows assigning two specific roles:- Contributor (b24988ac-6180-42a0-ab88-20f7382dd24c)
- Storage Blob Data Contributor (ba92f5b4-2d11-453d-a403-e96b0029c9fe)
The ABAC condition from the updated role definition:
((!(ActionMatches{'Microsoft.Authorization/roleAssignments/write'})) OR
(@Request[Microsoft.Authorization/roleAssignments:RoleDefinitionId]
ForAnyOfAnyValues:GuidEquals {ba92f5b4-2d11-453d-a403-e96b0029c9fe,
b24988ac-6180-42a0-ab88-20f7382dd24c}))Not only is this the correct approach, it also makes it much clearer what the role is intended for. The role can still assign the two roles that IoT Operations onboarding actually needs, but the privilege escalation path is closed. Any attempt to assign Owner or anything else is denied.
Takeaways
For defenders: Don't trust built-in role names and descriptions blindly. Audit the actual permissions. If you're using PIM, consider treating any role with roleAssignments/write as privileged regardless of Microsoft's classification.
For researchers: A simple script and a few minutes of scrolling uncovered a privilege escalation that Microsoft classified as "Important". With over 800 built-in roles and new ones shipping constantly, especially in areas like AI and IoT, there are almost certainly going to be more of these "unprivileged" gems hiding in plain sight. Go find them.
For Microsoft: ABAC conditions on role assignment permissions should be the default for any built-in role that needs to create role assignments. Shipping roles with broad authorization wildcards and then fixing them after researchers report them isn't sustainable.
Timeline
- 11.02.2026 – Discovered the overprivileged permission in the Azure IoT Operations Onboarding role and reported it to MSRC
- 18.03.2026 – MSRC acknowledged and began investigating
- 24.03.2026 – Fix deployed, role updated with ABAC condition
- 02.04.2026 – Verified fix
- 07.04.2026 – $10,000 bounty reward payout
Acknowledgements
- Microsoft Security Response Center (MSRC) for confirming the issue and shipping a solid fix.
- Ariel Simon and Token Security for the prior research on overprivileged Azure built-in roles that provided useful context for this finding.