What it is
A role assignment whose permissions are already fully covered by another assignment the same principal holds: the same role at a parent scope, or a higher role at the same or a broader scope. Owner supersedes Contributor, which supersedes Reader, so a lower grant sitting underneath a higher one changes no effective permission at all.
Why it happens
Access accumulates. Someone gets subscription-wide Contributor, then later gets Contributor on one specific resource group "to be safe," or Reader gets added on top of an existing Owner. Azure evaluates the union of every assignment a principal holds, so the extra grant is functionally harmless.
Because it never breaks anything and never triggers a warning, a redundant assignment has no reason to ever be removed. It just sits there. The same thing happens across scope levels: a grant at a resource group is redundant when the identity already holds that role at the subscription or management group above it.
What it costs / blast radius
There is no dollar cost and no added access — that is precisely the problem. (Azure behavior; authored assessment.) The harm is entirely hygiene: every redundant row inflates access reviews, obscures who actually needs what, and makes least-privilege analysis harder. Worse, when you eventually try to reduce someone's access, redundant assignments hide the one grant that is actually load-bearing, so removals get slower and riskier.
See it
resource ownerRa 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
name: guid(resourceGroup().id, principalId, 'Owner')
properties: {
roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')
principalId: principalId
principalType: 'User'
}
}
resource readerRa 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
// Owner already includes every Reader permission at this scope — this grant adds nothing
name: guid(resourceGroup().id, principalId, 'Reader')
properties: {
roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fbee2aae')
principalId: principalId
principalType: 'User'
}
}// Owner is the only assignment that carries any weight. Keep it, drop the rest.
resource ownerRa 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
name: guid(resourceGroup().id, principalId, 'Owner')
properties: {
roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')
principalId: principalId
principalType: 'User'
}
}
// (If the intent was actually narrower, keep the scoped Reader and remove the broad Owner instead.)How StratoLens helps
StratoLens flags assignments that are already covered by a broader or higher grant, whether that comes from a parent scope or a superseding role, so access reviews show real permissions instead of duplicated noise. It runs across every subscription in your tenant continuously, turning a cluttered assignment list back into an honest one.