prowler-cloud/prowler
View on GitHub[New Check]: Mailbox primary SMTP address must use a verified custom domain (not .onmicrosoft.com)
Open
#11069 opened on May 6, 2026
feature-requestgood first issuenew-checkprovider/m365
Description
Existing check search
- I have searched existing issues, Prowler Hub, and the public roadmap, and this check does not already exist.
Provider
Microsoft 365
New provider name
No response
Service or product area
exchange
Suggested check name
exchange_mailbox_primary_smtp_uses_custom_domain
Context and goal
- Security condition to validate: Every user-facing Exchange Online mailbox in the tenant uses a primary SMTP address on a verified custom domain — never the default
*.onmicrosoft.comrouting domain. - Why it matters: The
*.onmicrosoft.comdomain is the routing domain Microsoft assigns to every tenant on creation; it is not intended for ongoing day-to-day mail. Mailboxes that still send and receive on this domain leak the internal tenant identifier in every From: header (helping attackers fingerprint the tenant for spear-phishing), bypass DMARC/DKIM hardening that customers deploy on their custom domains, and frequently get treated as low-trust by recipients' anti-phishing engines. Microsoft's own admin guidance recommends moving every mailbox onto a verified custom domain after onboarding and reserving the.onmicrosoft.comaddress as a fallback. - Resource involved: Exchange Online mailboxes (
Get-Mailbox) and theirPrimarySmtpAddress.
Expected behavior
- Resource or scope to evaluate: All recipient-facing mailboxes returned by
Get-Mailbox -ResultSize Unlimitedof typesUserMailbox,SharedMailbox,RoomMailbox, andEquipmentMailbox. For each, inspectPrimarySmtpAddress. - PASS when: every evaluated mailbox's
PrimarySmtpAddressresolves to a domain that is not under*.onmicrosoft.com. Empty tenants (no mailboxes) also PASS. - FAIL when: at least one evaluated mailbox has
PrimarySmtpAddressunder*.onmicrosoft.com. The finding should report the mailboxIdentity,RecipientTypeDetails, and the offendingPrimarySmtpAddress. - MANUAL when: Exchange Online PowerShell is unavailable for the run — the check cannot complete and should report MANUAL with a status message asking the operator to enable EXO PowerShell.
- Exclusions / edge cases:
- Skip system-generated mailboxes by recipient type:
DiscoveryMailbox,ArbitrationMailbox,AuditLogMailbox,MonitoringMailbox,AuxAuditLogMailbox, and any mailbox taggedSystemMailbox. Those are managed by Microsoft and routinely keep the.onmicrosoft.comprimary address by design. - The check intentionally does not verify that secondary
EmailAddressesare also off.onmicrosoft.com. The policy concern is the primary (the address used for outbound mail and From: header). Audit of secondary addresses can be a follow-up.
- Skip system-generated mailboxes by recipient type:
References
- Microsoft 365 admin — Add a custom domain to Microsoft 365: https://learn.microsoft.com/en-us/microsoft-365/admin/setup/add-domain
- Microsoft 365 admin — Domains FAQ (
onmicrosoft.comprimary domain guidance): https://learn.microsoft.com/en-us/microsoft-365/admin/setup/domains-faq - Exchange Online PowerShell —
Get-Mailbox: https://learn.microsoft.com/en-us/powershell/module/exchange/get-mailbox - Exchange Online — Manage user mailboxes (recipient management overview): https://learn.microsoft.com/en-us/exchange/recipients-in-exchange-online/manage-user-mailboxes/manage-user-mailboxes
Suggested severity
Low
Additional implementation notes
- Existing patterns to follow: Sibling checks
exchange_user_mailbox_auditing_enabledandexchange_shared_mailbox_sign_in_disabledalready enumerate mailboxes via the existing Exchange Online PowerShell wiring inprowler/providers/m365/services/exchange/exchange_service.py. Reuse that same enumeration; exposeRecipientTypeDetailsandPrimarySmtpAddresson the loaded mailbox model if not already present. - Permissions / scopes: No additional permissions beyond what the
exchangeservice already requires (Exchange Online PowerShell access). No Microsoft Graph permissions are needed for this check. - PowerShell IS required; mailbox listings are not exposed via Microsoft Graph in a way that gives
PrimarySmtpAddressreliably across all recipient types. - Exclusion list constant: Define the system-mailbox
RecipientTypeDetailsexclusion list as a module-level constant so it is easy to extend if Microsoft introduces new recipient subtypes. - Metadata: follow the Exchange metadata schema used by sibling checks under
exchange/. SetResourceTypetomicrosoft.exchange/mailboxes.