The Problem
Inbox rules in Exchange Online help automate email management – forwarding messages, organizing folders, or flagging items. But there’s a lesser-known risk: some inbox rules are hidden from standard PowerShell queries. These can be used for legitimate purposes – like automatic replies – but can also be abused by threat actors.
🚨 Hidden inbox rules have been used in real-world cyberattacks to forward sensitive emails, maintain persistence, and evade detection – even after a user resets their password or MFA settings.
Hidden Inbox Rules as a Security Risk
As Soteria highlights, attackers with compromised credentials often create inbox rules that:
- Automatically forward emails to external addresses
- Delete or move emails to obscure folders
- Stay hidden from normal administrative reviews
These rules can help attackers exfiltrate sensitive information or maintain access silently.
That’s why proactively discovering hidden rules is not only good hygiene – it’s essential for security.
The Solution
To detect only hidden inbox rules, the following PowerShell script:
- Scans all user mailboxes
- Compares visible vs. all rules (
-IncludeHidden) - Filters out known system rules like:
- Flags corrupted rules with an
HasErrorsfield - Cleans multi-line descriptions for smooth CSV export
Script Breakdown
Filtering Out Known System Rules
$excludedNames = @(
"Junk E-mail Rule",
"Microsoft.Exchange.OOF.InternalSenders.Global",
"Microsoft.Exchange.OOF.KnownExternalSenders.Global",
"Microsoft.Exchange.OOF.AllExternalSenders.Global"
)
- $excludedNames: A predefined list of default system rules that are common and not security-relevant.
- These are excluded from results to reduce noise.
Getting All Mailboxes
$mailboxes = Get-Mailbox -RecipientTypeDetails UserMailbox -ResultSize Unlimited
- Get-Mailbox: Retrieves all user mailboxes in the tenant.
- UserMailbox: Filters out shared, resource, or system mailboxes.
- ResultSize Unlimited: Ensures we get the full list, not just the first 1000.
Looping Through Each Mailbox
foreach ($mbx in $mailboxes) {
$visibleRules = Get-InboxRule -Mailbox $mbx.PrimarySmtpAddress
$allRules = Get-InboxRule -Mailbox $mbx.PrimarySmtpAddress -IncludeHidden
}
- foreach: Iterates through every mailbox to check their inbox rules.
- -IncludeHidden: Ensures even the rules normally not returned by default are captured.
Isolating Hidden Rules Only
$hiddenRules = $allRules | Where-Object {
$visibleRules.Name -notcontains $_.Name -and
$excludedNames -notcontains $_.Name
}
- Where-Object: Filters out visible rules and any system rules from
$excludedNames. - The result: only hidden, non-standard rules remain.
Detecting Errors in Rules
$hasErrors = $rule.ToString() -like "*contains errors*"
- ToString(): Captures warning text not exposed as a property.
- “contains errors”: Checks for broken or malformed rules that may need manual review.
Cleaning Up Descriptions for CSV
$cleanDescription = ($rule.Description -replace '\r?\n', ' ').Trim()
- Removes line breaks (
\r\n) that would break CSV formatting. - Ensures the full rule description stays in one line.
Exporting the Results
$results | Export-Csv -Path ".\HiddenInboxRules_Report.csv" -NoTypeInformation -Encoding UTF8
- Export-Csv: Outputs the results to a file for review or auditing.
- UTF8 encoding: Ensures compatibility with Excel and international characters.
Sample Output
The final report contains:
- Mailbox address
- Rule name
- Status (Enabled/Disabled)
- Normalized rule description
HasErrorsflag for corrupted or unreadable rules
Pro Tip
Consider integrating this script into a regular audit routine or alerting system. If you see forwarding rules to suspicious domains or rules created without proper naming – investigate further.
Summary
Hidden inbox rules may seem like a technical curiosity, but they represent a real threat vector when abused. As an Exchange or M365 admin, having visibility into these rules is a powerful way to spot red flags early.
Better safe than breached.
Script Source
Complete script as always is available for download on azure365addict GitHub. Feel free to customize the script to fit your specific needs and improve your device management processes. If you have any questions or need further assistance, feel free to reach out!
Happy scripting!

