Role assignment policy does not allow Outlook add-ins
Microsoft 365 Exchange Online role assignment policies are assessed for roles that permit installing or managing Outlook add-ins (such as My Marketplace Apps, My Custom Apps, My ReadWriteMailbox Apps, Org Marketplace Apps, Org Custom Apps). Presence of these roles indicates users or admins can deploy add-ins from the store or custom sources.
Risk
Allowing add-in installation exposes mailboxes to malicious or vulnerable add-ins. With ReadWriteMailbox, an add-in can read, copy, or alter messages, auto-forward mail, and access tokens, enabling data exfiltration, message tampering, and lateral movement, impacting confidentiality and integrity.
Run this check with Prowler
Run in Prowler Cloudprowler m365 --checks exchange_roles_assignment_policy_addins_disabledRecommendation
Enforce least privilege for add-ins: remove add-in roles from end-user policies, reserve add-in management for trusted admins, and only deploy vetted add-ins via an allowlist. Review role assignment policies regularly to sustain defense in depth and prevent unapproved extensions.
Remediation
CLI
Get-ManagementRoleAssignment -RoleAssigneeType RoleAssignmentPolicy | Where-Object {$_.Name -like "My Custom Apps-*" -or $_.Name -like "My Marketplace Apps-*" -or $_.Name -like "My ReadWriteMailbox Apps-*"} | Remove-ManagementRoleAssignment -Confirm:$falseOther
Check Code
from typing import List
from prowler.lib.check.models import Check, CheckReportM365
from prowler.providers.m365.services.exchange.exchange_client import exchange_client
from prowler.providers.m365.services.exchange.exchange_service import AddinRoles
class exchange_roles_assignment_policy_addins_disabled(Check):
"""Check if any Exchange role assignment policy allows Outlook add-ins.
Attributes:
metadata: Metadata associated with the check (inherited from Check).
"""
def execute(self) -> List[CheckReportM365]:
"""Execute the check for role assignment policies that allow Outlook add-ins.
This method checks all Exchange Online Role Assignment Policies to verify
whether any of them allow the installation of add-ins by including risky roles.
Returns:
List[CheckReportM365]: A list of reports containing the result of the check.
"""
findings = []
addin_roles = [e.value for e in AddinRoles]
for policy in exchange_client.role_assignment_policies:
report = CheckReportM365(
metadata=self.metadata(),
resource=policy,
resource_name=policy.name,
resource_id=policy.id,
)
report.status = "PASS"
report.status_extended = f"Role assignment policy '{policy.name}' does not allow Outlook add-ins."
risky_roles_found = []
for role in policy.assigned_roles:
if role in addin_roles:
risky_roles_found.append(role)
if risky_roles_found:
report.status = "FAIL"
report.status_extended = f"Role assignment policy '{policy.name}' allows Outlook add-ins via roles: {', '.join(risky_roles_found)}."
findings.append(report)
return findings