Back to Checks
At least one Conditional Access policy enforces Identity Protection user risk for high-risk users
entra_identity_protection_user_risk_enabled
Service: entraSeverity: high
OfficialBuilt-inVerified
Categories:identity-accesse5
Resource Type:NotDefined
Microsoft Entra Conditional Access has a user risk-based policy that targets All users and All applications, evaluates High user risk, and actively enforces controls requiring both multifactor authentication and a secure password change with an AND condition.
Risk
Without an active High user-risk policy that forces MFA and secure password reset, compromised identities can persist, enabling data exfiltration, tampering, and privilege escalation. Report-only mode or narrow scope leaves gaps, undermining confidentiality and integrity across resources.
Run this check with Prowler
Run in Prowler CloudRun
prowler m365 --checks entra_identity_protection_user_risk_enabledRecommendation
Adopt least privilege by enabling an active user-risk policy that:
- covers
Allusers and apps (exclude only break-glass) - triggers on
Highuser risk - requires MFA and a secure password change together
- reauthenticates risky sessions
Pair with sign-in risk policies, ensure MFA registration, and review risky-user reports to validate effectiveness.
Remediation
Terraform
resource "azuread_conditional_access_policy" "<example_resource_name>" {
display_name = "<example_resource_name>"
state = "enabled"
conditions {
client_app_types = ["all"]
users {
include_users = ["All"] # Critical: targets all users
}
applications {
included_applications = ["All"] # Critical: applies to all cloud apps
}
user_risk_levels = ["high"] # Critical: enforces on high user risk
}
grant_controls {
operator = "AND" # Critical: require all selected controls
built_in_controls = ["mfa", "passwordChange"] # Critical: require MFA and password change
}
}Other
1Sign in to the Microsoft Entra admin center and go to Protection > Conditional Access > Policies
2Click New policy
3Users or workload identities: select All users
4Target resources (Cloud apps): select All cloud apps
5Conditions > User risk: set Configure to Yes and select High
6Access controls > Grant: select Grant access, then check Require multifactor authentication and Require password change; set Require all selected controls
7Enable policy: On, then click Create
Check Code
from prowler.lib.check.models import Check, CheckReportM365
from prowler.providers.m365.services.entra.entra_client import entra_client
from prowler.providers.m365.services.entra.entra_service import (
ConditionalAccessGrantControl,
ConditionalAccessPolicyState,
GrantControlOperator,
RiskLevel,
)
class entra_identity_protection_user_risk_enabled(Check):
"""Check if at least one Conditional Access policy is an Identity Protection user risk policy.
This check ensures that at least one Conditional Access policy is an Identity Protection user risk policy.
"""
def execute(self) -> list[CheckReportM365]:
"""Execute the check to ensure that at least one Conditional Access policy is an Identity Protection user risk policy.
Returns:
list[CheckReportM365]: A list containing the results of the check.
"""
findings = []
report = CheckReportM365(
metadata=self.metadata(),
resource={},
resource_name="Conditional Access Policies",
resource_id="conditionalAccessPolicies",
)
report.status = "FAIL"
report.status_extended = "No Conditional Access Policy is a user risk based Identity Protection Policy."
for policy in entra_client.conditional_access_policies.values():
if policy.state == ConditionalAccessPolicyState.DISABLED:
continue
if "All" not in policy.conditions.user_conditions.included_users:
continue
if (
"All"
not in policy.conditions.application_conditions.included_applications
):
continue
if (
ConditionalAccessGrantControl.PASSWORD_CHANGE
not in policy.grant_controls.built_in_controls
or ConditionalAccessGrantControl.MFA
not in policy.grant_controls.built_in_controls
or policy.grant_controls.operator != GrantControlOperator.AND
):
continue
if policy.conditions.user_risk_levels:
report = CheckReportM365(
metadata=self.metadata(),
resource=policy,
resource_name=policy.display_name,
resource_id=policy.id,
)
if RiskLevel.HIGH not in policy.conditions.user_risk_levels:
report.status = "FAIL"
report.status_extended = f"Conditional Access Policy '{policy.display_name}' is a user risk based Identity Protection Policy but does not protect against high risk potential account compromises."
elif policy.state == ConditionalAccessPolicyState.ENABLED_FOR_REPORTING:
report.status = "FAIL"
report.status_extended = f"Conditional Access Policy '{policy.display_name}' is a user risk based Identity Protection Policy and reports high risk potential account compromises, but does not protect against them."
else:
report.status = "PASS"
report.status_extended = f"Conditional Access Policy '{policy.display_name}' is a user risk based Identity Protection Policy and does protect against high risk potential account compromises."
break
findings.append(report)
return findings