Back to Checks
m365

Role assignment policy does not allow Outlook add-ins

exchange_roles_assignment_policy_addins_disabled
Service: exchangeSeverity: high
OfficialBuilt-inVerified
Categories:identity-accesse3
Resource Type:NotDefined

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 Cloud
Run
prowler m365 --checks exchange_roles_assignment_policy_addins_disabled

Recommendation

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:$false

Other

1Sign in to the Exchange admin center: https://admin.exchange.microsoft.com
2Go to Roles > User roles
3For each role assignment policy:
4- Select the policy > Manage permissions
5- Under Other roles, uncheck: My Custom Apps, My Marketplace Apps, My ReadWriteMailbox Apps
6- Save changes
7Repeat for all role assignment policies so none include these three roles

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