Back to BEC Investigation
Forwarding Audit
POST
/api/v1/bec/forwarding-auditAudit Microsoft 365 mailboxes for mail forwarding rules that could indicate data exfiltration. Detects SMTP forwarding, inbox rules with redirect actions, and transport rules. Each finding is risk-scored based on destination analysis, rule behavior, and creation timing.
Permissions
MailboxSettings.Read
Organization.Read.All
bec:read
Credits
5 per request
Plans
All plans
Timeout
120 seconds
CLI Usage
Terminal
# Audit a single user dfir-cli bec forwarding-audit --user admin@contoso.com # Audit all users in the tenant dfir-cli bec forwarding-audit --all-users # Audit users from a file, external-only, flag freemail providers dfir-cli bec forwarding-audit --user-file targets.txt \ --external-only --flag-freemail # Include transport rules and inbox rules, filter by risk dfir-cli bec forwarding-audit --user admin@contoso.com \ --include-transport-rules --include-inbox-rules \ --risk-threshold high --since 2026-01-01
Flags
| Flag | Type | Description |
|---|---|---|
| --user | string | Target user email address (UPN) to audit |
| --all-users | bool | Audit all mailboxes in the tenant |
| --user-file | string | Path to a file containing one UPN per line |
| --batch | int | Batch size for multi-user scans (default: 10) |
| --external-only | bool | Only report forwarding to external destinations |
| --flag-freemail | bool | Flag destinations using freemail providers (Gmail, ProtonMail, etc.) |
| --include-transport-rules | bool | Include Exchange transport rules in the audit |
| --include-inbox-rules | bool | Include Outlook inbox rules with redirect/forward actions |
| --since | string | Only include rules created after this date (ISO 8601) |
| --risk-threshold | string | Minimum risk level to report: "low", "medium", "high", "critical" |
| --concurrency | int | Number of concurrent mailbox scans (default: 5) |
Request Body
{
"user": "admin@contoso.com",
"all_users": false,
"external_only": true,
"flag_freemail": true,
"include_transport_rules": false,
"include_inbox_rules": true,
"since": "2026-01-01T00:00:00Z",
"risk_threshold": "medium",
"concurrency": 5
}| Field | Type | Required | Description |
|---|---|---|---|
| user | string | No | Target user UPN. Required if all_users is false. |
| all_users | boolean | No | Audit every mailbox in the tenant. Default: false. |
| external_only | boolean | No | Only return findings forwarding to external domains. Default: false. |
| flag_freemail | boolean | No | Add a risk factor for freemail provider destinations. Default: false. |
| include_transport_rules | boolean | No | Include Exchange transport (mail flow) rules. Default: false. |
| include_inbox_rules | boolean | No | Include Outlook inbox rules with forward/redirect actions. Default: true. |
| since | string | No | ISO 8601 date. Only include rules created after this timestamp. |
| risk_threshold | string | No | Minimum risk level to include: "low", "medium", "high", "critical". Default: "low". |
| concurrency | integer | No | Max parallel mailbox scans. Default: 5. |
Response
{
"data": [],
"meta": {
"total_findings": 0,
"by_type": {},
"critical": 0,
"high": 0,
"medium": 0,
"low": 0,
"credits_used": 5,
"credits_remaining": 4883
}
}
// When forwarding rules are detected, each finding looks like:
// {
// "type": "inbox_rule",
// "user": "admin@contoso.com",
// "destination": "attacker@gmail.com",
// "risk_score": 85,
// "risk_level": "critical",
// "risk_factors": [
// { "category": "external_forwarding", "description": "Forwards to external address: attacker@gmail.com", "score": 30 },
// { "category": "free_email_provider", "description": "Forwards to free email provider: attacker@gmail.com", "score": 25 },
// { "category": "match_all_forwarding", "description": "Match-all rule with forwarding (no conditions set)", "score": 40 }
// ],
// "is_enabled": true,
// "rule_name": "(unnamed)",
// "created_date_time": "",
// "modified_date_time": ""
// }| Field | Type | Description |
|---|---|---|
| data.findings | array | Array of forwarding findings across all scanned mailboxes |
| data.findings[].type | string | "smtp_forwarding", "inbox_rule", or "transport_rule" |
| data.findings[].user | string | UPN of the mailbox where the forwarding was found |
| data.findings[].destination | string | Email address or domain the mail is being forwarded to |
| data.findings[].risk_score | number | Risk score from 0 to 100 |
| data.findings[].risk_level | string | "critical", "high", "medium", or "low" |
| data.findings[].risk_factors | string[] | List of risk factors that contributed to the score |
| data.findings[].is_enabled | boolean | Whether the forwarding rule is currently active |
| data.findings[].rule_name | string | null | Name of the inbox/transport rule, or null for SMTP forwarding |
| data.findings[].created_at | string | ISO 8601 timestamp when the rule was created |
| data.summary | object | Aggregate counts by risk level and scan coverage |
| meta.credits_used | number | Credits consumed by this request (5) |
| meta.credits_remaining | number | Remaining credit balance after this request |
Risk Scoring
Each forwarding finding is assigned a risk score based on multiple factors. The risk_level is derived from the score:
| Score Range | Level |
|---|---|
| 80 – 100 | critical |
| 60 – 79 | high |
| 30 – 59 | medium |
| 0 – 29 | low |
Risk factors that increase the score include: external_destination, freemail_provider, recently_created, hidden_from_address_list, moves_to_deleted_items, marks_as_read, and broad_subject_match.
Finding Types
| Type | Source | Description |
|---|---|---|
| smtp_forwarding | Mailbox Settings | SMTP-level forwarding configured on the mailbox (ForwardingSMTPAddress). Always checked. |
| inbox_rule | Outlook Rules | Inbox rules with ForwardTo, RedirectTo, or ForwardAsAttachmentTo actions. Requires --include-inbox-rules. |
| transport_rule | Exchange Admin | Organization-level mail flow rules with redirect or BCC actions. Requires --include-transport-rules. |
Important Notes
- Requires an active Microsoft 365 connection. Run
dfir-cli bec statusto verify your session before auditing. - MailboxSettings.Read permission is required for SMTP forwarding and inbox rules. Organization.Read.All is additionally required for transport rules.
- The
--all-usersflag scans every licensed mailbox. For large tenants, use--concurrencyto control API throttling and--batchto process in chunks. - Costs 5 credits per request regardless of the number of users scanned.