At 09:40 on the Monday after a policy change, the service desk queue turns red: “I can’t get my invoices,” “the vendor portal link is broken,” “my scanned PO went to quarantine.” You tightened Defender for Office 365 over the weekend — enabled the Strict preset, raised an impersonation threshold, added a couple of protected users — and now legitimate mail is landing in quarantine while the users who actually get targeted still forward you the phish that slipped through. This is the defining tension of Microsoft Defender for Office 365 (MDO): the gap between “on” and “tuned” is exactly where both help-desk tickets and missed phish live, and every knob you turn trades a little coverage against a little friction.
Defender for Office 365 is the email and collaboration security layer that sits on top of Exchange Online Protection (EOP). EOP is the always-on anti-spam and anti-malware engine every Exchange Online mailbox already has; MDO adds the three engines this article is about — Safe Attachments (sandbox detonation of files), Safe Links (URL rewrite plus click-time re-checking), and anti-phishing with impersonation and mailbox intelligence. The verdicts you fight over — a quarantined invoice, a rewritten partner link, an impersonation flag on a look-alike sender — all come out of these engines, and the reason they misfire is almost never the engine being “wrong.” It is a policy scoped too broadly, a threshold set too aggressively, a spoof handled by disabling protection instead of allow-listing one pair, or a simulation vendor exempted with a transport rule that quietly punches a hole through every layer.
This is the tuning playbook. We treat Safe Links, Safe Attachments, and anti-phishing not as three checkboxes but as one layered system with a strict precedence order you must map before you touch anything, a set of actions each with a distinct user-visible consequence, and a small number of supported override surfaces (the Tenant Allow/Block List, Advanced Delivery, admin submissions) that fix false positives without lowering protection for everyone else. Everything is driven from Exchange Online PowerShell because that is the only sane way to keep policy in source control and diff it across tenants — the Microsoft Defender portal GUI (Email & collaboration → Policies & rules → Threat policies) shows the same objects but hides the precedence that decides which one actually applies. By the end you will know which engine emits which verdict, which knob moves it, and how to graduate protection by risk so the executives who get spear-phished are covered by Strict while the marketing team’s bulk mail is not being quarantined by an over-eager impersonation rule.
# Connect with the modern module (interactive or app-only)
Install-Module -Name ExchangePowerShell -Scope CurrentUser
Connect-ExchangeOnline -UserPrincipalName admin@contoso.onmicrosoft.com
What problem this solves
MDO ships with defaults that are deliberately conservative, and a Default policy that applies to everyone. That is safe but under-tuned: the general population gets no impersonation protection unless you configure it, Safe Links does not cover Teams or Office apps out of the box in older configurations, and the built-in protection order means a custom policy you think is applying may be silently overridden by a preset. The information you need — which policy matched this recipient, why this message was quarantined, what detection technology fired — is all captured and available, but it lives across the Defender portal’s Explorer, the message headers, the policy objects, and the audit log, and if you do not know which surface answers which question you burn an afternoon per incident.
What breaks without disciplined tuning: an admin “fixes” a false positive by adding a transport rule that sets SCL to -1 for a vendor domain (disabling Safe Links, Safe Attachments, and spoof intelligence for that entire path — a bypass attackers will ride the moment they learn the domain), or disables spoof intelligence to silence one alert (removing spoof protection for the whole policy population), or sets every anti-phish threshold to maximum and drowns the SOC in false positives on legitimate bulk mail. Meanwhile a genuinely targeted user — the CFO whose name a look-alike domain is spoofing — has no user-impersonation protection because nobody scoped it to them. The engines are fine; the configuration is the incident.
Who hits this: every organisation running Exchange Online with MDO Plan 1 or Plan 2. It bites hardest on tenants that rolled a preset to everyone without mapping their partner mail-authentication posture first (freight, EDI, and marketing relays that fail DMARC alignment get quarantined en masse), on tenants that never separated VIP protection from the general population (so thresholds are either too soft for executives or too hard for everyone), and on any team that treats the Tenant Allow/Block List and admin submissions as optional rather than as the only correct way to override a verdict. The fix is almost never “turn the engine off” — it is “scope the policy to the right people, graduate the threshold by risk, and override the one verdict that is wrong through a supported, time-boxed surface.”
To frame the whole field before the deep dive, here is every engine this article covers, what it protects against, what its most common false-positive source is, and the one supported lever to relieve that false positive:
| Engine | Protects against | Layer | Most common false positive | Supported relief lever |
|---|---|---|---|---|
| Safe Attachments | Weaponised file payloads (unknown malware) | MDO on top of EOP anti-malware | Legitimate archive/macro doc detonated slowly or blocked | Tenant Allow/Block List file hash; admin submission |
| Safe Links | Malicious URLs, weaponised-after-delivery links | MDO | Partner tracking/redirect link rewritten or blocked | Tenant Allow/Block List URL allow; DoNotRewriteUrls (sparingly) |
| Anti-phishing (impersonation) | Look-alike user/domain spear-phish, BEC | MDO | Legitimate look-alike sender flagged as impersonation | Policy ExcludedSenders/ExcludedDomains; trusted senders/domains |
| Anti-phishing (mailbox intelligence) | Impersonation of a user’s frequent contacts | MDO | New legitimate contact resembling a frequent one | Junk action (MoveToJmf) for general pop; exclusion |
| Anti-phishing (spoof intelligence) | Unauthenticated senders spoofing your/other domains | EOP (surfaced in MDO anti-phish) | Bulk relay failing DMARC alignment for a real partner | Tenant Allow/Block List spoof entry (one pair) |
Learning objectives
By the end of this article you can:
- Explain how Defender for Office 365 layers on top of EOP, which engine emits which verdict, and how a message flows through anti-malware → Safe Attachments → anti-spam/spoof → anti-phishing → Safe Links.
- Map any recipient to the exactly one policy that applies per protection type, given the fixed precedence order (Strict preset → Standard preset → custom policies by priority → Default), and confirm it with PowerShell.
- Configure Safe Attachments end to end — Block vs Dynamic Delivery vs Replace vs Monitor, quarantine policy, redirect, and the global SharePoint/OneDrive/Teams + Safe Documents settings — and pick the right action per mailbox class.
- Configure Safe Links end to end — URL rewrite, click-time detonation, scan-before-deliver, Teams and Office coverage, click-through, the
DoNotRewriteUrlslist — and explain the click-time flow that catches links weaponised after delivery. - Tune anti-phishing — user impersonation, domain impersonation, mailbox intelligence, spoof intelligence, the phishing confidence slider (
PhishThresholdLevel1–4), and the trusted senders/domains escape hatch — graduating thresholds by risk without generating false positives. - Decide between preset and custom policies, scope presets to VIPs vs the general population, and use the Tenant Allow/Block List and Advanced Delivery (phishing simulations, SecOps mailboxes) as the only supported override surfaces.
- Run a false-positive triage loop driven by admin submissions and time-boxed allow entries, and read the diagnostic surfaces (Threat Explorer/real-time detections, message headers, detection technology) that tell you why a message was actioned.
Prerequisites & where this fits
You should already understand Exchange Online basics: an accepted domain, mail flow (connectors and transport rules), quarantine, and the difference between the envelope sender (MAIL FROM / P1) and the visible From header (P2). You should know how to run Exchange Online PowerShell with the ExchangePowerShell module (formerly EXO V3), read the object model where each protection has a policy (settings) and a rule (recipient conditions + priority) linked by name, and navigate the Microsoft Defender portal to Email & collaboration → Policies & rules → Threat policies. Familiarity with SPF, DKIM, and DMARC alignment is important, because most spoof-intelligence “false positives” are actually a partner’s broken mail-auth posture.
This sits in the Microsoft 365 security track, downstream of EOP fundamentals and upstream of incident response. EOP’s anti-spam and connection filtering are covered in Tuning Exchange Online Protection: Anti-Spam, Connection Filtering, and Quarantine Policies — read that to understand the layer MDO sits on. The spoof-intelligence side depends entirely on mail authentication, so Enforcing Email Authentication for Exchange Online: SPF, DKIM, and DMARC From Monitoring to Reject is a hard prerequisite for getting spoof verdicts right. Day-two operations — running the quarantine and the Tenant Allow/Block List for SecOps — live in Operating the Defender for Office 365 Quarantine and Tenant Allow/Block List for SecOps, and the human-risk side is in Running Defender for Office 365 Attack Simulation Training: Payloads, Automations, and Repeat Offenders.
A quick map of who owns which layer, so you route incidents to the right team:
| Layer | What lives here | Who usually owns it | Verdicts / false positives it causes |
|---|---|---|---|
| Mail authentication (SPF/DKIM/DMARC) | Sender’s DNS + alignment | Partner / your DNS team | Spoof intelligence flags; unauthenticated-sender tips |
| EOP anti-spam / connection filter | SCL, bulk (BCL), IP allow/block | Messaging admin | Bulk/spam quarantine; false-positive on marketing |
| EOP anti-malware | Signature-based malware block | Messaging admin | Known-malware block (rarely a false positive) |
| MDO Safe Attachments | Sandbox detonation of unknown files | Security / messaging | Slow/blocked legitimate attachments |
| MDO Safe Links | URL rewrite + click-time detonation | Security / messaging | Rewritten/blocked partner links |
| MDO anti-phishing | Impersonation, mailbox intelligence, spoof action | Security | Impersonation flags on look-alike legit senders |
| Override surfaces (TABL, Advanced Delivery, submissions) | Allow/block entries, simulation/SecOps exemptions | Security / SecOps | Where you fix false positives correctly |
Core concepts
Six mental models make every later tuning decision obvious.
EOP is the floor; MDO is the layer on top. Every Exchange Online mailbox already has Exchange Online Protection — connection filtering, anti-spam (the Spam Confidence Level, SCL), anti-malware (signature-based), and spoof intelligence. Defender for Office 365 adds detonation and impersonation intelligence on top: Safe Attachments re-examines files EOP anti-malware already passed, Safe Links wraps URLs, and MDO anti-phishing adds user/domain impersonation and mailbox intelligence to the spoof protection EOP already provides. When you tune, you are almost always tuning the MDO layer — but the verdict a user complains about (a bulk newsletter in quarantine) may be an EOP verdict, so the first question is always “which layer actioned this?”
Each protection is a policy plus a rule, and a recipient matches exactly one. For each of Safe Attachments, Safe Links, and anti-phishing there is a policy object (the settings — actions, thresholds, lists) and a rule object (the recipient conditions plus a numeric priority). They are linked by name. Defender evaluates policies of a given type by priority order (lower number wins) and a recipient is matched by exactly one policy per type — the first one whose rule conditions it satisfies. This is the single most important fact in the whole article: if a user is covered by the Strict preset, that user is never evaluated against your custom Safe Links policy, no matter how you set its priority.
The protection order is fixed and presets always win. Across all policies of a type the flat order is: Strict preset → Standard preset → custom policies (in explicit priority 0, 1, 2…) → Default policy. Presets are a special case — they do not appear in Get-SafeAttachmentPolicy and cannot have their security settings edited (that is the point; Microsoft maintains them). The only knobs on a preset are scope (who it applies to) and, for the impersonation part, the protected users/domains and trusted senders. If you need to change a threshold, you need a custom policy — and you must scope your presets so they do not swallow the population you want the custom policy to reach.
Actions have distinct user-visible consequences, and quarantine policies gate what users can do. Each engine’s action determines what happens to a message: Safe Attachments can Block, Dynamic Delivery, Replace, or Monitor; anti-phishing can Quarantine, Move to Junk, or add a safety tip; Safe Links can block click-through or warn. When something is quarantined, a separate quarantine policy (e.g. AdminOnlyAccessPolicy, DefaultFullAccessWithNotificationPolicy) decides whether the user can view it, release it themselves, or must request release. Tuning friction is largely about matching the action’s severity and the quarantine policy’s permissiveness to the verdict’s confidence.
Impersonation and spoof are different mechanisms with different fixes. Spoof intelligence (an EOP feature, actioned in the anti-phish policy) is about authentication — a message whose visible From domain is not authenticated (SPF/DKIM/DMARC) by the sending infrastructure. Impersonation (an MDO feature) is about similarity — a message from a different but look-alike user or domain (a typosquat, or a display-name match). A partner whose relay fails DMARC alignment trips spoof; a contoso-legaI.com (capital-I for lowercase-l) trips domain impersonation. You fix spoof false positives with a Tenant Allow/Block List spoof entry (one sending-infrastructure/domain pair); you fix impersonation false positives with a policy trusted sender/domain exclusion. Confusing the two is why people disable the wrong engine.
Overrides belong on supported surfaces, always time-boxed. The correct places to override a verdict are the Tenant Allow/Block List (TABL) (URLs, file hashes, domains/senders, spoof pairs), the Advanced Delivery policy (phishing simulations and SecOps mailboxes), and admin submissions (which both time-box an allow and send the sample to Microsoft for reclassification). The wrong places are transport rules that set SCL -1 (a total bypass) and disabling an engine (removes protection for the whole population). Every allow entry should have an expiration — a -NoExpiration allow quietly accumulates into a permanent, unaudited bypass list.
The vocabulary in one table
Before the deep sections, pin down every moving part. The glossary at the end repeats these for lookup; this table is the mental model side by side:
| Concept | One-line definition | Where it lives | Why it matters to tuning |
|---|---|---|---|
| EOP | Always-on anti-spam/malware/spoof for every mailbox | Exchange Online | The floor MDO layers on; emits many “false positives” |
| MDO (Plan 1/2) | Detonation + impersonation intelligence add-on | On top of EOP | The layer you tune; Plan gates investigation not config |
| Policy | The settings object (actions, thresholds, lists) | Per protection type | What you edit to change behaviour |
| Rule | Recipient conditions + numeric priority | Per protection type | Decides who the policy applies to |
| Priority order | Lower number wins; one policy per recipient | Across all rules of a type | Why a policy may silently not apply |
| Preset (Standard/Strict) | Microsoft-maintained, uneditable settings | Special preset objects | Always outrank custom; scope-only knobs |
| Safe Attachments action | Block / Dynamic Delivery / Replace / Monitor | Safe Attachments policy | Determines file-delivery friction |
| Safe Links click-time | Re-checks the URL when the user clicks | Safe Links wrapper | Catches links weaponised after delivery |
| Impersonation | Look-alike user/domain (similarity) | Anti-phish policy | Fixed via trusted sender/domain exclusion |
| Spoof intelligence | Unauthenticated From domain (authentication) |
EOP, actioned in anti-phish | Fixed via TABL spoof entry, not by disabling |
PhishThresholdLevel |
Phishing confidence slider (1–4) | Anti-phish policy | Higher = more aggressive = more false positives |
| TABL | Tenant Allow/Block List (URL/file/domain/spoof) | Tenant-wide | The supported override surface |
| Advanced Delivery | Exempt phishing-sim + SecOps mailboxes | Tenant-wide | The only correct way to exempt those flows |
| Quarantine policy | What users may do with quarantined items | Referenced by each policy | The lever that cuts help-desk load |
How a message flows through EOP and MDO
Tuning is guesswork until you know the order in which a message is examined, because the engine that actions a message is the one whose stage it failed at, and the header stamps you read to confirm a verdict correspond to these stages. An inbound message is processed roughly in this sequence — earlier stages can short-circuit later ones (a message blocked as malware never reaches anti-phishing):
| # | Stage | Engine / layer | What it decides | Header / signal it stamps |
|---|---|---|---|---|
| 1 | Connection filtering | EOP | IP allow/block, connection reputation | CIP in X-Forefront-Antispam-Report |
| 2 | Anti-malware (signature) | EOP | Known malware → delete/quarantine | CTRY/malware verdict; message deleted |
| 3 | Safe Attachments | MDO | Detonate unknown files → Block/Replace/Dynamic Delivery | Detection tech “Safe Attachments file detonation” |
| 4 | Mail flow / transport rules | Exchange | Org rules (can override SCL — dangerous) | X-MS-Exchange-Organization-Transport-Rules |
| 5 | Anti-spam + spoof intelligence | EOP | SCL/BCL, composite auth (spoof) | SCL, BCL, CompAuth in header |
| 6 | Anti-phishing (impersonation + MI) | MDO | User/domain impersonation, mailbox intelligence | Detection tech “Impersonation user/domain”, “Mailbox intelligence” |
| 7 | Safe Links (at delivery) | MDO | Rewrite URLs; scan-before-deliver holds message | X-MS-Exchange-Organization-* URL verdict |
| 8 | Delivery to mailbox / quarantine | Exchange | Final placement per policy action + quarantine policy | Quarantine reason; X-Microsoft-Antispam |
| 9 | Safe Links (at click) | MDO | Re-check reputation when user clicks the wrapped URL | Click event in URL clicks report |
Two reading notes save the most time. First, Safe Links has two moments: at delivery (rewrite, and optionally hold the message until the URL is scanned) and at click (re-check the reputation of the destination). A link that was clean at delivery and weaponised an hour later is caught at stage 9, not stage 7 — this is the whole reason URL rewrite exists. Second, the composite authentication result (CompAuth) in the header is where spoof lives: CompAuth=fail with a reason code is the signal a message failed the authentication checks that spoof intelligence acts on, and it is what you read to distinguish a spoof verdict from an impersonation verdict.
The composite-auth values you will read most, and what each tells you:
CompAuth reason |
Meaning | Typical cause | Tuning implication |
|---|---|---|---|
pass |
Message authenticated (SPF/DKIM/DMARC aligned or allowed by spoof intel) | Legitimate, aligned sender | No spoof action |
fail (e.g. reason=000/001) |
Explicit auth failure | DMARC reject/quarantine, or spoof intel blocked | Spoof action fired — fix at TABL spoof, not by disabling |
softpass |
Passed via a secondary signal (e.g. spoof intel allow, or ARC) | Partner previously allowed, or ARC-sealed | Watch for over-broad spoof allow |
none |
No auth checks applicable | Internal or specially-routed mail | Verify routing didn’t skip auth |
Presets vs custom policies and precedence
Before you configure a single engine, decide your policy strategy and map your population, because precedence determines everything and it is not intuitive.
The fixed protection order
Across all policies of a given type, the flat evaluation order is:
- Strict preset security policy (highest priority — always wins where its scope applies)
- Standard preset security policy
- Custom policies, in their explicit priority order (0 is evaluated first)
- The Default policy (always last — applies to everyone not matched above)
A recipient is matched to the first policy (in that order) whose rule conditions it satisfies, and to exactly one policy per protection type. The consequence: a user in the Strict preset scope is never evaluated against a custom Safe Links policy, and a custom policy at priority 0 still loses to both presets. Map who is in the presets before you build custom policies, or you will spend hours debugging “my policy isn’t applying.”
Inspect the live ordering for every protection type — this is the first command you run on any tenant you inherit:
# Preset rules (EOP part covers anti-spam/malware/anti-phish; ATP part covers Safe Links/Attachments)
Get-EOPProtectionPolicyRule | Sort-Object Priority | Format-Table Name, State, Priority, SentToMemberOf
Get-ATPProtectionPolicyRule | Sort-Object Priority | Format-Table Name, State, Priority, SentToMemberOf
# Custom rules in priority order
Get-SafeAttachmentRule | Sort-Object Priority | Format-Table Name, Priority, State, SentTo, SentToMemberOf, RecipientDomainIs
Get-SafeLinksRule | Sort-Object Priority | Format-Table Name, Priority, State, SentTo, SentToMemberOf
Get-AntiPhishRule | Sort-Object Priority | Format-Table Name, Priority, State, SentTo, SentToMemberOf
The preset vs custom decision
The fastest path to strong, Microsoft-maintained protection is a preset. Presets auto-update as Microsoft tightens recommended values, and the Strict preset is genuinely strict — more aggressive quarantine, lower impersonation thresholds, tighter bulk handling. Custom policies exist for the narrow cases presets cannot express. Choose deliberately:
| Dimension | Standard preset | Strict preset | Custom policy | Default policy |
|---|---|---|---|---|
| Who maintains the settings | Microsoft | Microsoft | You | Microsoft (baseline) |
| Auto-updates with MS recommendations | Yes | Yes | No | Partly |
| Security settings editable | No (scope only) | No (scope only) | Yes (everything) | Limited |
| Aggressiveness | Balanced | High (more quarantine) | Whatever you set | Conservative baseline |
| Impersonation config | Add protected users/domains + trusted senders | Same | Full control of thresholds/actions | Off by default |
| Best for | General population | VIPs, finance, legal, admins | Partner-specific tuning, per-dept actions | Fallback for unmatched recipients |
| Precedence | 2nd | 1st (highest) | By explicit priority | Last |
A pragmatic enterprise pattern: Strict preset for high-risk targets (executives, finance, legal, IT admins), Standard preset for the general population, and custom policies only for genuinely special cases — a partner domain needing a tuned impersonation allow-list, or a department that needs Safe Attachments Dynamic Delivery while an automation-only mailbox needs Block. Scope the presets explicitly (both the EOP and ATP rule for the same preset must be set — they are separate objects):
# Scope the Strict preset to specific groups — EOP + ATP rules must BOTH be set
Set-EOPProtectionPolicyRule -Identity "Strict Preset Security Policy" `
-SentToMemberOf "Tier0-Admins","Finance-Leadership","Legal"
Set-ATPProtectionPolicyRule -Identity "Strict Preset Security Policy" `
-SentToMemberOf "Tier0-Admins","Finance-Leadership","Legal"
# Scope the Standard preset to everyone (the common pattern)
Set-EOPProtectionPolicyRule -Identity "Standard Preset Security Policy" -SentTo $null -SentToMemberOf $null -RecipientDomainIs "contoso.com"
Set-ATPProtectionPolicyRule -Identity "Standard Preset Security Policy" -RecipientDomainIs "contoso.com"
The impersonation settings are editable on presets (they are the exception), so you add protected users/domains and trusted senders to a preset without needing a custom policy:
# Add protected users/domains + trusted exclusions to the Strict preset's impersonation config
Set-AntiPhishPolicy -Identity "Strict Preset Security Policy" `
-TargetedUsersToProtect "CEO;ceo@contoso.com","CFO;cfo@contoso.com","General Counsel;gc@contoso.com" `
-TargetedDomainsToProtect "contoso.com","contoso-legal.com" `
-ExcludedSenders "noreply@trusted-saas.com" -ExcludedDomains "trusted-saas.com"
The trap to internalise: if you need a threshold changed (a different PhishThresholdLevel, a Safe Attachments action the preset doesn’t use), you cannot do it on a preset — you build a custom policy, and you must ensure your presets’ scope doesn’t cover the recipients you want the custom policy to reach. The interaction of the four policy tiers, and how to reason about it:
| If a recipient is in… | They are evaluated against… | To give them different settings… |
|---|---|---|
| Strict preset scope | Strict preset only | Remove from Strict scope, then Standard or custom applies |
| Standard preset scope (not Strict) | Standard preset only | Remove from Standard scope, then custom or Default applies |
| A custom policy’s rule (no preset) | The highest-priority custom policy they match | Reorder custom priorities, or narrow the rule |
| No preset and no custom match | The Default policy | Edit the Default policy (limited) or add a custom policy |
Safe Attachments: detonation, actions, and global settings
Safe Attachments detonates unknown attachments in a sandbox before delivery, catching zero-day malware that signature-based EOP anti-malware misses. The friction cost is latency — sandbox detonation takes time — which is why the action you pick matters enormously for user experience.
The four actions
# Custom Safe Attachments policy with Dynamic Delivery (best for human mailboxes)
New-SafeAttachmentPolicy -Name "SA-Standard" `
-Enable $true `
-Action DynamicDelivery `
-QuarantineTag "AdminOnlyAccessPolicy" `
-Redirect $false
# Bind it to recipients with a rule (priority 0 = first among custom)
New-SafeAttachmentRule -Name "SA-Standard" `
-SafeAttachmentPolicy "SA-Standard" `
-RecipientDomainIs "contoso.com" `
-Priority 0
The Action value is the decision that shapes user experience. Each behaves differently and suits a different mailbox class:
Action (-Action) |
What happens to the message | User experience | Best for | Trade-off / gotcha |
|---|---|---|---|---|
Block |
Message + attachment blocked/quarantined until verdict; malicious → stays blocked | May wait; malicious never delivered | Shared/automation mailboxes; highest-risk users | Highest friction; benign files also wait for detonation |
DynamicDelivery |
Body delivered immediately; attachment reattached after scan (or removed if malicious) | Reads mail now, attachment lands seconds later | Human mailboxes (recommended) | Only for email; a placeholder shows briefly; not for all file types |
Replace |
Malicious attachment stripped, body + notification delivered | Gets the message, sees a “removed” notice | Environments preferring delivery over hold | Loses the benign-until-proven-guilty nuance; strips on detection |
Monitor (aka Allow/Off + track) |
Delivers, records the verdict, takes no blocking action | No friction | Tuning/observation phase only | No protection — never leave in prod |
Use DynamicDelivery for human mailboxes (it neutralises the latency by delivering the body immediately) and Block for shared or automation mailboxes that should never receive attachments in the first place. Never leave Monitor in production — it detonates and records but does not act.
Redirect, quarantine policy, and the “unavailable” behaviour
Two more settings on the policy:
| Setting | Values | Default | When to change | Trade-off / gotcha |
|---|---|---|---|---|
Redirect |
$true/$false + RedirectAddress |
$false |
Security team wants copies of malicious attachments | Only meaningful with Block/Replace; sends the payload to a mailbox |
QuarantineTag |
A quarantine policy name | AdminOnlyAccessPolicy |
Loosen so users can request release of benign-blocked files | Loosening malware release is a security decision |
-RedirectAddress |
Mailbox address | none | With Redirect $true only |
The recipient receives real malware — isolate it |
AdminOnlyAccessPolicy is the right default for Safe Attachments quarantine — a detonated-malicious file should not be self-releasable by an end user. If Safe Attachments cannot complete detonation (a scanning error), the platform’s “unavailable” behaviour applies; for high-security tenants you want that to fail closed, which the Block action enforces.
Global settings: SharePoint, OneDrive, Teams, and Safe Documents
Safe Attachments for email is only half the story. A separate global setting protects files at rest and in collaboration — SharePoint Online, OneDrive for Business, and Teams — independent of mail flow, plus Safe Documents (E5) that detonates files opened in Office Protected View:
# Global ATP for SharePoint/OneDrive/Teams + Safe Documents
Set-AtpPolicyForO365 -EnableATPForSPOTeamsODB $true `
-EnableSafeDocs $true `
-AllowSafeDocsOpen $false
The AllowSafeDocsOpen value is a small decision with large consequences:
| Global setting | Values | Recommended | What it protects | Gotcha |
|---|---|---|---|---|
EnableATPForSPOTeamsODB |
$true/$false |
$true |
Files uploaded/shared in SPO/ODB/Teams | Blocks download of files flagged malicious in collaboration |
EnableSafeDocs (E5) |
$true/$false |
$true |
Files opened in Office Protected View | Requires E5 / E5 Security |
AllowSafeDocsOpen |
$true/$false |
$false |
Whether a file failing detonation can still be opened | $true lets users bypass — a classic postmortem line |
AllowSafeDocsOpen $false means a file that fails detonation in Protected View stays blocked; setting it $true lets users click past — convenient, and exactly the kind of “small” decision that becomes an incident postmortem. Keep it $false.
Safe Links: rewrite, click-time detonation, and coverage
Safe Links rewrites URLs through a Microsoft wrapper and re-checks the destination’s reputation at click time, which is what catches links that were clean at delivery and weaponised afterward. The defaults are strong; tuning is mostly about breadth of coverage and a minimal trusted-URL list.
The click-time flow
When Safe Links is active, an inbound URL https://example.com/x is rewritten to a Microsoft wrapper URL. At delivery, if scan-before-deliver is on, the message is held until the URL is scanned; the original may also be detonated. At click, the wrapper intercepts the request, re-evaluates the destination’s current reputation, and either passes the user through, shows a warning (with click-through blocked if you configured it), or blocks. The sequence, and what each step gives you:
| Step | Moment | What Safe Links does | Why it matters |
|---|---|---|---|
| 1 | Delivery | Rewrite URL to the Safe Links wrapper | Every click now routes through Microsoft’s reputation check |
| 2 | Delivery (DeliverMessageAfterScan) |
Hold message until URL scan completes | The first click is protected, not just later ones |
| 3 | Delivery (detonation) | Detonate suspicious URLs in a sandbox | Catches malicious destinations before any user clicks |
| 4 | Click | Re-check destination reputation now | Catches links weaponised after delivery |
| 5 | Click (AllowClickThrough=$false) |
Block the user from proceeding past the warning | The single biggest self-inflicted gap when set $true |
| 6 | Click (TrackClicks) |
Record the click for reporting/hunting | Feeds the URL clicks report and Explorer |
Configuring Safe Links end to end
New-SafeLinksPolicy -Name "SL-Standard" `
-EnableSafeLinksForEmail $true `
-EnableSafeLinksForTeams $true `
-EnableSafeLinksForOffice $true `
-ScanUrls $true `
-DeliverMessageAfterScan $true `
-DisableUrlRewrite $false `
-EnableForInternalSenders $true `
-TrackClicks $true `
-AllowClickThrough $false `
-CustomNotificationText "Links in this message are protected. Verify before entering credentials."
New-SafeLinksRule -Name "SL-Standard" `
-SafeLinksPolicy "SL-Standard" `
-RecipientDomainIs "contoso.com" `
-Priority 0
Every Safe Links knob, what it does, its default, and when you change it:
| Setting | What it does | Recommended | Values | When to change / gotcha |
|---|---|---|---|---|
EnableSafeLinksForEmail |
Protect URLs in email | $true |
$true/$false |
Off leaves email URLs unwrapped |
EnableSafeLinksForTeams |
Protect URLs in Teams chats/channels | $true |
$true/$false |
Teams is a real phishing vector — keep on |
EnableSafeLinksForOffice |
Protect URLs opened in Office desktop/web/mobile apps | $true |
$true/$false |
Covers links in Word/Excel/PowerPoint |
ScanUrls |
Scan URLs at delivery time | $true |
$true/$false |
Off disables delivery-time scanning |
DeliverMessageAfterScan |
Hold the message until URL scan completes | $true |
$true/$false |
Protects the first click; slight delivery delay |
DisableUrlRewrite |
Turn OFF the visible rewrite (still click-checked in some clients) | $false |
$true/$false |
$true reduces visible wrapping but weakens some protection |
EnableForInternalSenders |
Rewrite/scan links in internal mail too | $true |
$true/$false |
Catches internal-account compromise fan-out |
TrackClicks |
Record user clicks | $true |
$true/$false |
Off loses click telemetry for hunting |
AllowClickThrough |
Let users proceed past the warning page | $false |
$true/$false |
$true is the single biggest self-inflicted gap |
DoNotRewriteUrls |
Per-policy do-not-rewrite list | empty | URL patterns | Prefer TABL; be surgical with wildcards |
CustomNotificationText |
Text on the warning page | your string | free text | Reinforce “verify before entering credentials” |
The two settings that most affect user trust are AllowClickThrough (keep $false — allowing users past the warning is the biggest gap audits find) and DeliverMessageAfterScan ($true so the first click is protected, not just later ones).
The trusted-URL list and wildcard danger
For trusted URL exclusions, prefer the tenant-level list (via TABL, section on overrides) over per-policy entries so exclusions are centralised and auditable. When you must use the per-policy DoNotRewriteUrls, be surgical:
# Per-policy do-not-rewrite (use sparingly, scoped to a full path)
Set-SafeLinksPolicy -Identity "SL-Standard" `
-DoNotRewriteUrls "https://partner.example.com/portal/*"
The wildcard rules matter because a lazy pattern silently disables protection for far more than you intend:
Pattern in DoNotRewriteUrls |
What it actually excludes | Risk |
|---|---|---|
https://partner.example.com/portal/* |
Only that host + path prefix | Acceptable if you truly trust the whole portal |
partner.example.com/* |
The whole host, any path | Broader than needed; a compromised path is now unprotected |
*.example.com/* |
Every subdomain of the domain | Dangerous — a compromised subdomain gets zero click-time protection |
*contoso* |
Anything containing “contoso” anywhere | Reckless — matches attacker contoso.evil.com |
A bare *.example.com turns off click-time protection for every host under that domain, including a subdomain an attacker later compromises. Scope to the full path you actually trust, and review the list quarterly.
Anti-phishing: impersonation, mailbox intelligence, and spoof
This is where false positives are won or lost. The anti-phish policy has three distinct engines — user/domain impersonation, mailbox intelligence, and spoof intelligence — each with its own threshold and its own allow-list, and each with a different correct fix when it misfires.
The full anti-phish policy
New-AntiPhishPolicy -Name "AP-Strict-VIP" `
-Enabled $true `
-PhishThresholdLevel 3 `
-EnableMailboxIntelligence $true `
-EnableMailboxIntelligenceProtection $true `
-MailboxIntelligenceProtectionAction Quarantine `
-EnableTargetedUserProtection $true `
-TargetedUsersToProtect "CEO;ceo@contoso.com","CFO;cfo@contoso.com" `
-TargetedUserProtectionAction Quarantine `
-EnableTargetedDomainsProtection $true `
-TargetedDomainsToProtect "contoso.com","contoso-legal.com" `
-TargetedDomainProtectionAction Quarantine `
-EnableOrganizationDomainsProtection $true `
-EnableSimilarUsersSafetyTips $true `
-EnableSimilarDomainsSafetyTips $true `
-EnableSpoofIntelligence $true `
-AuthenticationFailAction Quarantine `
-EnableUnauthenticatedSender $true `
-EnableViaTag $true `
-EnableFirstContactSafetyTips $true
New-AntiPhishRule -Name "AP-Strict-VIP" `
-AntiPhishPolicy "AP-Strict-VIP" `
-SentToMemberOf "Finance-Leadership","Tier0-Admins" `
-Priority 0
The phishing confidence slider
PhishThresholdLevel is the master aggressiveness dial for the phishing verdict — how confident the ML must be before it acts. It runs 1 to 4:
PhishThresholdLevel |
Portal label | Behaviour | When to use | False-positive risk |
|---|---|---|---|---|
| 1 | Standard | Least aggressive; acts on high-confidence phish only | Default general population | Low |
| 2 | Aggressive | Acts on more borderline messages | General population wanting tighter | Low–moderate |
| 3 | More aggressive | Acts on many borderline messages | VIPs / high-risk groups | Moderate |
| 4 | Most aggressive | Acts on the widest set | Rarely — only very high-risk, well-tuned | High — hits legitimate bulk/marketing |
Start at 1–2 for the general population and 3 for VIPs. Jumping straight to 4 reliably generates false positives on legitimate bulk and marketing mail — the classic “we turned everything to max and drowned” mistake.
The three engines compared
Each engine catches a different attack and has a different correct fix:
| Engine | Enable parameter | What it catches | Action parameter | Correct false-positive fix |
|---|---|---|---|---|
| User impersonation | EnableTargetedUserProtection + TargetedUsersToProtect |
Look-alike of a named protected identity | TargetedUserProtectionAction |
Trusted senders (ExcludedSenders) |
| Domain impersonation | EnableTargetedDomainsProtection + TargetedDomainsToProtect |
Look-alike/typosquat of a protected domain | TargetedDomainProtectionAction |
Trusted domains (ExcludedDomains) |
| Org-domain impersonation | EnableOrganizationDomainsProtection |
Look-alike of any of your accepted domains | (uses domain action) | Trusted domains exclusion |
| Mailbox intelligence | EnableMailboxIntelligence + EnableMailboxIntelligenceProtection |
Impersonation of a user’s frequent contacts (learned graph) | MailboxIntelligenceProtectionAction |
Softer action (MoveToJmf) or exclusion |
| Spoof intelligence | EnableSpoofIntelligence |
Unauthenticated From domain (authentication failure) |
AuthenticationFailAction |
TABL spoof entry — never disable the engine |
How to reason about each:
- User impersonation protects named identities using the
Display Name;emailformat. Every protected user is a potential false-positive source against legitimate look-alikes (a real person named similarly, a partner with a close display name), so keep the list to genuinely high-risk people, not the whole org chart. - Domain impersonation catches typosquats (
c0ntoso.com,contoso-legaI.com).EnableOrganizationDomainsProtectionautomatically covers all your accepted domains without listing them. - Mailbox intelligence learns each user’s normal sender graph and flags impersonations of frequent contacts — very powerful, but for the general population use the gentler
MoveToJmf(Junk) rather thanQuarantineto avoid quarantining a new legitimate contact who resembles a frequent one. - Spoof intelligence is about authentication, not similarity — see the dedicated section below.
The impersonation and mailbox-intelligence action choices, and when each fits:
| Action value | Where valid | User consequence | Best for |
|---|---|---|---|
Quarantine |
User/domain/MI protection | Held; release per quarantine policy | VIPs; high-confidence protection |
MoveToJmf (Move to Junk) |
User/domain/MI/auth-fail | Lands in Junk Email | General population; gentler |
Delete |
Auth-fail / spoof | Silently dropped | Rare; only very high-confidence |
Redirect |
User/domain | Sent to a review mailbox | SOC review workflows |
NoAction + safety tip |
User/domain | Delivered with a warning tip | Tuning / low-risk observation |
The safety tips and sender-hygiene signals
Beyond the actioning engines, several safety tip signals help users without quarantining anything. Turn them on — they are low-friction and high-value:
| Parameter | What it shows the user | Recommended | Notes |
|---|---|---|---|
EnableFirstContactSafetyTips |
“You don’t often get email from this sender” | $true |
Cheap, effective anti-BEC signal |
EnableSimilarUsersSafetyTips |
Tip when a sender resembles a protected user | $true |
Complements user impersonation |
EnableSimilarDomainsSafetyTips |
Tip when a domain resembles a protected domain | $true |
Complements domain impersonation |
EnableUnauthenticatedSender |
The ? in the sender photo for unauthenticated mail |
$true |
Visual spoof cue in Outlook |
EnableViaTag |
“via” tag when From domain ≠ sending domain |
$true |
Flags relay/on-behalf mismatches |
Spoof intelligence: authentication, not similarity
Spoof intelligence acts on messages whose visible From domain is not authenticated by the sending infrastructure (SPF/DKIM/DMARC misalignment). The action is AuthenticationFailAction (Move to Junk or Quarantine), and EnableUnauthenticatedSender adds the visual cue. The critical rule: do not disable spoof intelligence to fix a single false positive. A legitimate partner whose bulk relay fails DMARC alignment will trip spoof — the fix is a Tenant Allow/Block List spoof entry for that exact sending-infrastructure/spoofed-domain pair, not turning off the engine (which removes spoof protection for the entire policy population) and not an SCL -1 transport rule.
# Exempt known-good senders/domains that trip IMPERSONATION (not spoof)
Set-AntiPhishPolicy -Identity "AP-Strict-VIP" `
-ExcludedSenders "noreply@trusted-saas.com" `
-ExcludedDomains "trusted-saas.com"
The decision table for anti-phish false positives — match the flag to the fix:
| If a legitimate message is flagged as… | The engine is… | The signal to confirm | The correct fix |
|---|---|---|---|
| Impersonation of a protected user | User impersonation | Detection tech “Impersonation user” | Add to ExcludedSenders (trusted sender) |
| Impersonation of a protected domain | Domain impersonation | Detection tech “Impersonation domain” | Add to ExcludedDomains (trusted domain) |
| Impersonation of a frequent contact | Mailbox intelligence | Detection tech “Mailbox intelligence” | Softer action, or exclude the sender |
Spoof (unauthenticated From) |
Spoof intelligence | CompAuth=fail; detection tech “Spoof” |
TABL spoof entry (one pair) + fix partner auth |
| Phishing (generic ML) | Phishing verdict | Detection tech “Phishing” | Lower PhishThresholdLevel or admin submission |
| Bulk/marketing in quarantine | EOP anti-spam (BCL) | High BCL in header |
Raise bulk threshold / EOP allow — not an MDO fix |
Override surfaces: TABL, Advanced Delivery, and admin submissions
There are exactly three supported ways to override a verdict. Using anything else (a transport rule with SCL -1, disabling an engine) creates a real, exploitable bypass.
The Tenant Allow/Block List (TABL)
TABL is the supported mechanism to override verdicts on URLs, files (by SHA256), domains/senders, and spoof pairs — tenant-wide, and (crucially) time-boxed:
# Inspect current entries
Get-TenantAllowBlockListItems -ListType Url
Get-TenantAllowBlockListItems -ListType FileHash
Get-TenantAllowBlockListItems -ListType Sender
Get-TenantAllowBlockListSpoofItems
# Allow a falsely blocked URL for a bounded window (let it expire on its own)
New-TenantAllowBlockListItems -ListType Url `
-Allow -Entries "https://newsletter.partner.com/track*" `
-ExpirationDate (Get-Date).AddDays(30) `
-Notes "FP - partner newsletter, ticket INC-4821"
# Block a known-bad file hash permanently (block entries may be indefinite)
New-TenantAllowBlockListItems -ListType FileHash `
-Block -Entries "0123abcd...<sha256>..." -NoExpiration
# Allow a specific spoofed pair (partner relay failing DMARC alignment)
New-TenantAllowBlockListSpoofItems `
-Action Allow `
-SpoofType External `
-SendingInfrastructure "mail.partner-relay.net" `
-SpoofedUser "bigfreight.com"
The four TABL list types, what they override, and their rules:
-ListType / cmdlet |
Overrides | Allow entries | Block entries | Gotcha |
|---|---|---|---|---|
Url |
URL verdicts (Safe Links) | Time-boxed (default 30 d, max ~90) | Can be indefinite | Match the exact URL/path; wildcards apply broadly |
FileHash |
Safe Attachments file verdicts | Time-boxed | Can be indefinite | SHA256 only; a re-saved file has a new hash |
Sender/Domain |
Sender/domain verdicts | Time-boxed | Can be indefinite | Over-broad domain allow weakens spoof protection |
Spoof (...SpoofItems) |
Spoof-intelligence verdicts | Per sending-infra/spoofed-user pair | Per pair | Scope to one pair; don’t allow a whole domain blind |
The governing rule: allow entries are for time-boxed false-positive relief; block entries can be indefinite. Never use -NoExpiration on an allow entry unless you own a recurring review — they quietly accumulate into a permanent bypass list nobody audits. And prefer admin submissions over directly creating allow entries, because a submission both creates a bounded allow and sends the sample to Microsoft for reclassification, fixing the root cause for everyone rather than masking it in your tenant.
Advanced Delivery: phishing simulations and SecOps mailboxes
Two legitimate flows must bypass filtering, and they must use the Advanced Delivery policy — never a mail-flow rule that skips filtering wholesale:
# SecOps mailbox override (where the SOC deliberately collects live phish)
$secops = Get-SecOpsOverridePolicy
if (-not $secops) { New-SecOpsOverridePolicy -Name "SecOps-Override" -SentTo "soc-phish@contoso.com" }
# Phishing simulation override (sending IPs + simulation URLs)
New-PhishSimOverridePolicy -Name "PhishSim-Override"
New-PhishSimOverrideRule -Policy "PhishSim-Override" `
-SenderIpRanges "203.0.113.0/24" `
-Domains "phishtraining.example"
Why Advanced Delivery and not a transport rule:
| Flow | Wrong way (creates a bypass) | Right way (Advanced Delivery) | Why it matters |
|---|---|---|---|
| Third-party phishing simulation | Transport rule SCL -1 for the vendor domain | PhishSim override (IPs + URLs) |
SCL -1 disables Safe Links/Attachments for that path; attackers spoofing the vendor ride it |
| SecOps analysis mailbox | Transport rule bypassing filtering | SecOps override (mailbox) |
Messages arrive intact for analysis without a global hole |
| Attack Simulation Training | (built-in — no override needed) | Native simulation is auto-exempt | Don’t hand-exempt what the platform already handles |
The Advanced Delivery policy is the correct and supported way to exempt these flows; using a transport rule with SCL -1 to whitelist a simulation vendor disables Safe Links and Safe Attachments for that path entirely, and threat actors who learn the vendor’s domains will spoof them.
Admin submissions and user reporting
Wire the user reporting endpoint so users have a self-service path that also feeds Microsoft:
# Route user reports to a mailbox AND to Microsoft
Set-ReportSubmissionPolicy -Identity DefaultReportSubmissionPolicy `
-EnableReportToMicrosoft $true `
-ReportJunkToCustomizedAddress $true `
-ReportNotJunkToCustomizedAddress $true `
-ReportPhishToCustomizedAddress $true `
-ReportJunkAddresses "soc-reports@contoso.com" `
-ReportNotJunkAddresses "soc-reports@contoso.com" `
-ReportPhishAddresses "soc-reports@contoso.com"
The three override surfaces at a glance, and when to reach for each:
| Surface | Overrides | Time-boxed? | Sends sample to Microsoft? | Reach for it when… |
|---|---|---|---|---|
| Admin submission | Any verdict (creates a matching allow) | Yes (bounded) | Yes | Fixing a false positive the right way — always the first choice |
| Tenant Allow/Block List | URL/file/sender/spoof directly | Yes for allows | No | You need an immediate, scoped allow/block and can’t wait for reclassification |
| Advanced Delivery | Phishing-sim + SecOps flows only | N/A (standing) | No | Exempting simulations or a SecOps mailbox — never for general mail |
Quarantine policies: the friction lever
When a policy quarantines a message, a separate quarantine policy decides what the user may do with it. This is the single lever that most reduces help-desk load without lowering protection — because most tickets are “release my quarantined newsletter,” and a notification-enabled quarantine policy lets users self-serve.
# See the built-in quarantine policies
Get-QuarantinePolicy | Format-Table Name, EndUserQuarantinePermissionsValue, ESNEnabled
The built-in quarantine policies and the user experience each gives:
| Quarantine policy | User can view | User can release | User can request release | Notification email | Use for |
|---|---|---|---|---|---|
AdminOnlyAccessPolicy |
No | No | No | No | Malware, high-confidence phish, Safe Attachments |
DefaultFullAccessPolicy |
Yes | Yes | Yes | No | Spam/bulk where self-release is fine |
DefaultFullAccessWithNotificationPolicy |
Yes | Yes | Yes | Yes | Spam/bulk — users self-serve via the notification |
The mapping rule: reserve admin-only release for malware and high-confidence phish (where an end user must never self-release), and map the least dangerous verdicts (spam, bulk) to a notification policy so users self-serve. That single alignment removes the majority of quarantine tickets.
Which quarantine policy each verdict should map to:
| Verdict | Confidence | Recommended quarantine policy | Rationale |
|---|---|---|---|
| Malware (EOP or Safe Attachments) | Certain | AdminOnlyAccessPolicy |
Never self-releasable |
| High-confidence phish | High | AdminOnlyAccessPolicy |
Too dangerous for self-release |
| Phish (standard) | Medium | AdminOnlyAccessPolicy or request-release |
Balance risk vs friction |
| Spoof / impersonation | Medium | Request-release or notification | Often a partner-auth false positive |
| Spam | Low | DefaultFullAccessWithNotificationPolicy |
Self-serve; high volume |
| Bulk / marketing | Low | DefaultFullAccessWithNotificationPolicy |
Almost always a false positive; self-serve |
Architecture at a glance
Picture the layered system as three concentric protections wrapped around every mailbox, with a small set of override surfaces off to the side. At the outer floor sits Exchange Online Protection: connection filtering scores the sending IP, anti-malware blocks known-bad files by signature, and anti-spam plus spoof intelligence evaluate the Spam Confidence Level and the composite-authentication result. Any message can be stopped here before it ever reaches the Defender layer — which is why a “false positive” is so often an EOP bulk or spoof verdict, not an MDO one.
Wrapped around that floor is the Defender for Office 365 layer, and it acts in a definite order as a message flows inward. First Safe Attachments detonates unknown files in a sandbox; depending on the policy action the body is delivered immediately with the attachment reattached after scanning (Dynamic Delivery), or the whole message waits (Block), or the file is stripped (Replace). Next anti-phishing applies its three engines — user and domain impersonation for look-alike senders, mailbox intelligence for impersonation of a user’s frequent contacts, and the spoof action for unauthenticated From domains — each with its own threshold and its own allow-list. Then Safe Links rewrites every URL to a Microsoft wrapper; if scan-before-deliver is on, the message is held until the URL is checked, and the original may be detonated. The message lands in the mailbox or in quarantine, where the referenced quarantine policy decides whether the user can self-release. The second, decisive moment for Safe Links comes later: when the user clicks the wrapped link, the wrapper re-checks the destination’s reputation right then, catching a URL that was clean at delivery and armed an hour afterward.
Governing all of this is precedence: every recipient is matched to exactly one policy per type, in the fixed order Strict preset → Standard preset → custom policies by priority → Default, so the settings that actually apply depend on which policy claims the recipient first. Off to the side sit the three override surfaces — the Tenant Allow/Block List (URL, file hash, sender/domain, spoof pair), the Advanced Delivery policy (phishing simulations and SecOps mailboxes), and admin submissions (which time-box an allow and send the sample to Microsoft). The whole discipline of tuning is this: localise a false positive to the engine and stage that produced it, confirm it from the detection technology and the message header, and relieve it through one of those three supported surfaces — never by disabling an engine or punching an SCL -1 hole through every layer at once.
Real-world scenario
Meridian Freight, a mid-sized logistics company with about 2,400 mailboxes on Microsoft 365 E5, rolled the Strict preset to its entire population the Thursday before quarter-end, reasoning that “more protection is better.” The security team was three people; the messaging admin was a fourth, part-time. Within two hours of the change, the AP (accounts-payable) team flooded the service desk: every inbound EDI transmission and carrier-rate confirmation from a long-standing freight partner, bigfreight.com, was landing in quarantine. By 11:00 the queue held 340 tickets and the finance controller had escalated to the CISO, because the quarter-end close depended on those rate confirmations being processed that day.
The reflex fixes made it worse. One engineer added a transport rule setting SCL -1 for bigfreight.com to “just let it through” — which released the backlog but silently disabled Safe Links and Safe Attachments for every message from that domain, a fact nobody noticed until the security review two weeks later. Another engineer proposed disabling spoof intelligence entirely to stop the flagging; the lead vetoed it, correctly, because that would have removed spoof protection for all 2,400 mailboxes during the highest-risk week of the quarter.
The breakthrough came from asking why the messages were quarantined rather than how to force them through. Opening a quarantined message in Threat Explorer and reading the detection technology showed “Spoof,” not impersonation and not malware — and the message header confirmed CompAuth=fail. The partner sent from a bulk relay whose envelope domain (mail.partner-relay.net) failed DMARC alignment against the visible From (@bigfreight.com). So spoof intelligence and unauthenticated-sender flagging (EnableUnauthenticatedSender $true, part of the Strict preset) were firing correctly — the partner’s mail-authentication posture was the actual problem, not Meridian’s policy. That reframing changed the fix entirely: this was not a policy to relax but a specific spoofed pair to allow.
The night-of fix was a scoped, time-boxed spoof allow in the Tenant Allow/Block List for the exact pair — SendingInfrastructure mail.partner-relay.net, SpoofedUser bigfreight.com — which released the backlog for that partner without disabling spoof intelligence for anyone else and without the SCL -1 hole. They also removed the transport rule the first engineer had added. The durable fix landed the following week: they asked the partner to publish Meridian’s relay in their SPF and align DMARC; once mail.partner-relay.net passed alignment, CompAuth returned pass, the spoof verdict stopped, and Meridian removed the TABL spoof allow entirely. The quarter closed on time. The lesson written on the wall: a preset rollout is a population event, and a partner’s mail-auth posture — not your policy — is often the actual root cause.
The incident as a timeline, because the order of moves is the lesson:
| Time | Symptom | Action taken | Effect | What it should have been |
|---|---|---|---|---|
| 09:15 | Strict preset applied to all | (change deployed) | — | Pilot on VIPs first; map partner auth |
| 09:40 | AP tickets start | (alert) | 340 tickets by 11:00 | Ask: which detection technology fired? |
| 10:20 | “Just let it through” | Transport rule SCL -1 for the domain | Backlog releases, silent bypass created | Never SCL -1 a domain |
| 10:45 | Proposal to disable spoof intel | Lead vetoes | Protection preserved | Correct call |
| 11:10 | Root cause found | Threat Explorer → detection tech “Spoof”; header CompAuth=fail |
Partner DMARC misalignment identified | The breakthrough |
| 11:30 | Mitigated correctly | TABL spoof allow (one pair); remove transport rule | Backlog clears, no global hole | Correct night-of fix |
| +1 week | Fixed durably | Partner publishes SPF + aligns DMARC; remove TABL allow | CompAuth=pass; spoof stops |
The actual root-cause fix |
Advantages and disadvantages
The layered, policy-and-rule model both causes this class of tuning problem and makes it precisely fixable. Weigh it honestly:
| Advantages (why the model helps you) | Disadvantages (why it bites) |
|---|---|
| Presets give Microsoft-maintained, auto-updating protection with zero threshold babysitting | Presets can’t have security settings edited, and they silently outrank custom policies you thought applied |
| Every verdict is attributable — detection technology + message headers tell you exactly which engine fired | The information is spread across Explorer, headers, and policy objects; you must know which answers which question |
| Supported override surfaces (TABL, Advanced Delivery, submissions) let you fix one false positive without lowering protection for everyone | The wrong fixes (SCL -1 transport rule, disabling an engine) are easy, tempting, and create real bypasses |
| Dynamic Delivery neutralises Safe Attachments latency; click-time Safe Links catches post-delivery weaponisation | Defaults are conservative — impersonation off, thresholds low — so an untuned tenant under-protects VIPs |
| Quarantine policies let users self-serve low-risk verdicts, cutting help-desk load | A too-permissive quarantine policy on a real phish lets a user self-release malware |
| Impersonation + mailbox intelligence catch BEC that signature engines miss | Over-broad impersonation lists turn the engine into a false-positive generator against legitimate look-alikes |
| Admin submissions fix the root cause for everyone by feeding Microsoft’s reclassification | Skipping submissions and hand-building allow entries masks the problem only in your tenant, and accumulates unaudited |
The model is right for any Exchange Online organisation that wants layered, ML-driven protection without operating its own mail-security stack. It bites hardest on tenants that roll presets to everyone without piloting, that never separate VIP from general-population protection, that reach for transport rules to “just fix it,” and that treat submissions as optional. Every disadvantage is manageable — but only if you know precedence, know which engine emits which verdict, and use the supported override surfaces, which is the entire point of tuning.
Hands-on lab
Build a graduated, low-false-positive configuration in a test tenant: scope presets by risk, add a custom Safe Attachments policy for an automation mailbox, tune anti-phishing for a VIP group, and handle a false positive the correct way via TABL. Run in Exchange Online PowerShell. This uses only configuration cmdlets (no billable resources); teardown removes everything you create.
Step 1 — Connect and capture the current state.
Connect-ExchangeOnline -UserPrincipalName admin@contoso.onmicrosoft.com
# Snapshot precedence so you can diff later
Get-EOPProtectionPolicyRule | Sort-Object Priority | Format-Table Name, State, Priority
Get-ATPProtectionPolicyRule | Sort-Object Priority | Format-Table Name, State, Priority
Get-SafeAttachmentRule | Sort-Object Priority | Format-Table Name, Priority, State
Get-SafeLinksRule | Sort-Object Priority | Format-Table Name, Priority, State
Get-AntiPhishRule | Sort-Object Priority | Format-Table Name, Priority, State
Expected: a list of any existing rules with their priorities. On a fresh tenant this is empty or shows only presets.
Step 2 — Scope the Strict preset to a VIP group and Standard to everyone.
# Assumes mail-enabled security groups "Lab-VIPs" and coverage of contoso.com exist
Set-EOPProtectionPolicyRule -Identity "Strict Preset Security Policy" -SentToMemberOf "Lab-VIPs"
Set-ATPProtectionPolicyRule -Identity "Strict Preset Security Policy" -SentToMemberOf "Lab-VIPs"
Set-EOPProtectionPolicyRule -Identity "Standard Preset Security Policy" -RecipientDomainIs "contoso.com"
Set-ATPProtectionPolicyRule -Identity "Standard Preset Security Policy" -RecipientDomainIs "contoso.com"
Expected: no error. Confirm with Get-EOPProtectionPolicyRule | Format-Table Name, SentToMemberOf, RecipientDomainIs.
Step 3 — Add a custom Safe Attachments policy that blocks for an automation mailbox.
New-SafeAttachmentPolicy -Name "SA-Automation-Block" -Enable $true -Action Block -QuarantineTag "AdminOnlyAccessPolicy" -Redirect $false
New-SafeAttachmentRule -Name "SA-Automation-Block" -SafeAttachmentPolicy "SA-Automation-Block" -SentTo "automation@contoso.com" -Priority 0
Expected: the policy and rule are created. Because this is a custom policy, the automation mailbox must not be in a preset scope for it to apply (verify with the precedence snapshot).
Step 4 — Tune anti-phishing for VIPs with a graduated threshold.
New-AntiPhishPolicy -Name "AP-Lab-VIP" -Enabled $true `
-PhishThresholdLevel 3 `
-EnableTargetedUserProtection $true -TargetedUsersToProtect "CEO;ceo@contoso.com" -TargetedUserProtectionAction Quarantine `
-EnableOrganizationDomainsProtection $true -TargetedDomainProtectionAction Quarantine `
-EnableMailboxIntelligence $true -EnableMailboxIntelligenceProtection $true -MailboxIntelligenceProtectionAction Quarantine `
-EnableSpoofIntelligence $true -AuthenticationFailAction Quarantine -EnableUnauthenticatedSender $true -EnableFirstContactSafetyTips $true
New-AntiPhishRule -Name "AP-Lab-VIP" -AntiPhishPolicy "AP-Lab-VIP" -SentToMemberOf "Lab-VIPs" -Priority 0
Expected: policy + rule created. Note this custom policy only applies if Lab-VIPs is not also swallowed by the Strict preset — if it is, remove that group from Strict scope or accept the preset’s values.
Step 5 — Enable global Safe Attachments for SharePoint/OneDrive/Teams and route user reports.
Set-AtpPolicyForO365 -EnableATPForSPOTeamsODB $true -EnableSafeDocs $true -AllowSafeDocsOpen $false
Set-ReportSubmissionPolicy -Identity DefaultReportSubmissionPolicy `
-EnableReportToMicrosoft $true -ReportPhishToCustomizedAddress $true -ReportPhishAddresses "soc-reports@contoso.com"
Expected: Get-AtpPolicyForO365 | Format-List EnableATPForSPOTeamsODB, EnableSafeDocs, AllowSafeDocsOpen shows True, True, False.
Step 6 — Handle a false positive the correct way (time-boxed TABL allow).
# A partner newsletter URL was blocked; allow it for 30 days (let it expire)
New-TenantAllowBlockListItems -ListType Url -Allow -Entries "https://newsletter.partner.com/track*" `
-ExpirationDate (Get-Date).AddDays(30) -Notes "Lab FP - partner newsletter"
# Confirm it landed and IS time-boxed
Get-TenantAllowBlockListItems -ListType Url | Format-Table Value, Action, ExpirationDate
Expected: the entry appears with a non-empty ExpirationDate roughly 30 days out. An empty ExpirationDate on an allow is the anti-pattern you are avoiding.
Validation checklist. You scoped presets by risk (Strict → VIPs, Standard → all), added a custom Block policy for automation, graduated the VIP phishing threshold to 3, enabled global collaboration protection, routed user reports to Microsoft and the SOC, and relieved a false positive through a time-boxed TABL allow — the supported surface. The steps mapped to what each proves:
| Step | What you did | What it proves | Real-world analogue |
|---|---|---|---|
| 2 | Scope Strict → VIPs, Standard → all | Precedence is scope-driven and deliberate | Graduating protection by risk |
| 3 | Custom Block for automation mailbox | Actions differ by mailbox class | Locking down a service mailbox |
| 4 | VIP anti-phish at threshold 3 | Thresholds graduate by risk | Protecting executives without drowning marketing |
| 6 | Time-boxed TABL allow | False positives get supported, expiring relief | Every real FP ticket |
Cleanup.
Remove-SafeAttachmentRule -Identity "SA-Automation-Block" -Confirm:$false
Remove-SafeAttachmentPolicy -Identity "SA-Automation-Block" -Confirm:$false
Remove-AntiPhishRule -Identity "AP-Lab-VIP" -Confirm:$false
Remove-AntiPhishPolicy -Identity "AP-Lab-VIP" -Confirm:$false
Get-TenantAllowBlockListItems -ListType Url -Entries "https://newsletter.partner.com/track*" |
ForEach-Object { Remove-TenantAllowBlockListItems -ListType Url -Ids $_.Identity }
# Reset preset scoping if this was a shared test tenant, then:
Disconnect-ExchangeOnline -Confirm:$false
Cost note. Configuration cmdlets are free; the cost is licensing — MDO Plan 1 (bundled with Business Premium) or Plan 2 (E5 / E5 Security). No per-operation charge and nothing to leave running.
Common mistakes & troubleshooting
This is the playbook — the part you bookmark. First a scannable table you can read mid-incident, then the entries that bite hardest expanded with the exact confirm step.
| # | Symptom | Root cause | Confirm (exact cmd / portal path) | Fix |
|---|---|---|---|---|
| 1 | Custom policy “not applying”; users still get preset behaviour | A preset outranks the custom policy for those recipients | Get-EOPProtectionPolicyRule/Get-ATPProtectionPolicyRule show the recipients in preset scope |
Remove them from preset scope, or fold the setting into the preset |
| 2 | Partner EDI/newsletters mass-quarantined after a change | Spoof verdict — partner relay fails DMARC alignment | Threat Explorer detection tech = “Spoof”; header CompAuth=fail |
TABL spoof allow (one pair); fix partner SPF/DMARC |
| 3 | Legitimate look-alike sender flagged as impersonation | User/domain impersonation on a real similar sender | Detection tech “Impersonation user/domain” | ExcludedSenders/ExcludedDomains on the policy |
| 4 | A vendor’s mail bypasses Safe Links/Attachments entirely | A transport rule set SCL -1 for that path | `Get-TransportRule | ? {$_.SetSCL -eq -1}` |
| 5 | Spoof false positive “fixed” but protection dropped for all | Someone disabled spoof intelligence on the policy | `Get-AntiPhishPolicy | ft Name, EnableSpoofIntelligence` |
| 6 | Container of false positives on bulk/marketing after “max” tuning | PhishThresholdLevel 4 too aggressive |
`Get-AntiPhishPolicy | ft Name, PhishThresholdLevel` |
| 7 | Phishing-sim emails get filtered/quarantined | Sim vendor not in Advanced Delivery | `Get-PhishSimOverrideRule | ft Domains, SenderIpRanges` |
| 8 | SecOps analysis mailbox never receives live phish intact | No SecOps override for that mailbox | `Get-SecOpsOverridePolicy | ft Name, SentTo` |
| 9 | Attachments arrive very slowly for everyone | Safe Attachments Action Block on human mailboxes |
`Get-SafeAttachmentPolicy | ft Name, Action` |
| 10 | Help-desk buried in “release my newsletter” tickets | Bulk/spam mapped to admin-only quarantine | Get-*Policy → check QuarantineTag/quarantine policy |
Map bulk/spam to DefaultFullAccessWithNotificationPolicy |
| 11 | Allow list grows forever; nobody knows why entries exist | -NoExpiration on allow entries |
`Get-TenantAllowBlockListItems -ListType Url | ? {-not $_.ExpirationDate}` |
| 12 | Safe Links wildcard exclusion left a subdomain unprotected | *.example.com in DoNotRewriteUrls |
`Get-SafeLinksPolicy | ft Name, DoNotRewriteUrls` |
| 13 | Users click straight through the Safe Links warning to malware | AllowClickThrough $true |
`Get-SafeLinksPolicy | ft Name, AllowClickThrough` |
| 14 | Impersonation flags on your own execs’ legit mail | Exec not excluded / mailbox-intel too strict for general pop | Detection tech “Mailbox intelligence”/“Impersonation user” | Exclude the exec’s real addresses; soften MI action for general pop |
The expanded form, with full reasoning for the entries that bite hardest:
1. A custom policy “isn’t applying” and users still get preset behaviour.
Root cause: the recipients are inside a preset’s scope, and presets outrank all custom policies regardless of the custom policy’s priority.
Confirm: Get-EOPProtectionPolicyRule and Get-ATPProtectionPolicyRule — check whether the recipients (or their groups/domain) appear in the Strict or Standard preset’s SentToMemberOf/RecipientDomainIs.
Fix: remove those recipients from the preset scope so the custom policy can match them, or (if you only need impersonation changes) fold the settings into the preset’s editable impersonation config instead.
2. Partner EDI or newsletters get mass-quarantined right after a policy change.
Root cause: a spoof verdict — the partner’s bulk relay fails DMARC alignment against the visible From, so spoof intelligence and unauthenticated-sender flagging fire correctly.
Confirm: open a quarantined message in Threat Explorer and read the detection technology — “Spoof,” not impersonation or malware; the message header shows CompAuth=fail.
Fix: add a TABL spoof allow for the exact SendingInfrastructure/SpoofedUser pair (time-boxed), then get the partner to publish you in SPF and align DMARC so the spoof verdict stops at the source and you can remove the allow. Never disable spoof intelligence and never SCL -1 the domain.
4. A vendor’s mail bypasses Safe Links and Safe Attachments entirely.
Root cause: someone added a transport rule setting SCL -1 for that vendor/domain to “fix” a false positive, which disables filtering — including Safe Links/Attachments — for that entire path.
Confirm: Get-TransportRule | Where-Object { $_.SetScl -eq -1 } | Format-Table Name, SentToScope, FromScope reveals the offending rule.
Fix: remove the SCL -1 rule; relieve the original false positive through TABL (URL/file/sender allow) or Advanced Delivery (for sim/SecOps). An SCL -1 domain is a bypass attackers ride by spoofing the domain.
5. A spoof false positive was “fixed” but spoof protection dropped for everyone.
Root cause: someone set EnableSpoofIntelligence $false on the anti-phish policy to silence one alert, removing spoof protection for the whole policy population.
Confirm: Get-AntiPhishPolicy | Format-Table Name, EnableSpoofIntelligence shows it False.
Fix: re-enable spoof intelligence and scope the relief to the single pair with a TABL spoof allow.
6. A flood of false positives on legitimate bulk/marketing after “turning everything up.”
Root cause: PhishThresholdLevel 4 (Most aggressive) applied broadly acts on legitimate borderline mail — bulk and marketing especially.
Confirm: Get-AntiPhishPolicy | Format-Table Name, PhishThresholdLevel shows 4 on a broad policy.
Fix: lower to 2 for the general population (3 for VIPs), and add specific trusted senders/domains for the few legitimate senders that still trip.
7. Phishing-simulation emails get filtered or quarantined.
Root cause: the simulation vendor’s sending IPs and URLs are not in the Advanced Delivery phishing-sim override.
Confirm: Get-PhishSimOverrideRule | Format-Table Domains, SenderIpRanges — the vendor is absent.
Fix: add the vendor’s IPs and simulation URLs to the PhishSim override — the supported exemption, not a transport rule.
9. Attachments arrive very slowly for ordinary users.
Root cause: Safe Attachments Action Block on human mailboxes holds every message until detonation completes.
Confirm: Get-SafeAttachmentPolicy | Format-Table Name, Action shows Block on a policy scoped to human mailboxes.
Fix: use DynamicDelivery for human mailboxes so the body is delivered immediately; reserve Block for shared/automation mailboxes.
11. The allow list grows without bound and nobody knows why entries exist.
Root cause: -NoExpiration on allow entries; each one becomes a permanent, unaudited bypass.
Confirm: Get-TenantAllowBlockListItems -ListType Url | Where-Object { -not $_.ExpirationDate } lists the offenders.
Fix: set an ExpirationDate on every allow, adopt admin submissions to create time-boxed allows automatically, and schedule a quarterly review.
Best practices
- Map precedence before you build anything. Run
Get-EOPProtectionPolicyRuleandGet-ATPProtectionPolicyRulefirst; know who is in each preset so a custom policy you add actually reaches its intended recipients. - Graduate protection by risk, not by “more is better.” Strict preset for VIPs/finance/legal/admins, Standard for the general population, custom policies only for genuinely special cases.
PhishThresholdLevel3 for VIPs, 1–2 for everyone else. - Use Dynamic Delivery for human mailboxes and Block for automation. Never leave Safe Attachments in
Monitorin production — it detonates but does not protect. - Keep
AllowClickThrough $falseandDeliverMessageAfterScan $trueon Safe Links. Allowing users past the warning, and not scanning before delivery, are the two biggest self-inflicted Safe Links gaps. - Keep impersonation lists narrow. Protect the people who are actually targeted, not the whole org chart — every protected user is a potential false-positive source against legitimate look-alikes.
- Fix spoof at the source, allow the pair meanwhile. A spoof false positive is a partner mail-auth problem; add a scoped TABL spoof allow now, get the partner to align DMARC, then remove the allow.
- Never use SCL -1 transport rules or disable an engine to fix a false positive. Use the Tenant Allow/Block List, Advanced Delivery, or admin submissions — the only surfaces that don’t create a bypass.
- Prefer admin submissions over hand-built allow entries. A submission time-boxes the allow and feeds Microsoft’s reclassification, fixing the root cause for everyone.
- Time-box every allow entry. No
-NoExpirationon allows without a recurring review; expiring entries keep the bypass surface honest. - Tier quarantine policies by verdict severity. Admin-only release for malware and high-confidence phish; notification-enabled self-release for bulk and spam to cut help-desk load.
- Handle phishing simulations and SecOps mailboxes via Advanced Delivery only. Not a transport rule that skips filtering wholesale.
- Source-control the PowerShell and diff every change. Treat policy as code; a rollout is a population event and should be reviewed like one.
Security notes
- Least-privilege administration. Managing these policies needs Security Administrator or a scoped role, not Global Administrator. Use Privileged Identity Management so the role is eligible and time-bound, per Zero Trust on Microsoft Entra: Conditional Access + PIM, Step by Step.
- App-only PowerShell for automation. For pipeline-driven policy management, use certificate-based app-only authentication to Exchange Online rather than a stored admin credential.
- Don’t weaken protection to fix friction. Every “temporary” bypass — a disabled engine, an SCL -1 rule, a
-NoExpirationallow — is a standing security hole. The supported surfaces relieve friction without lowering protection; use them. - Guard the override surfaces. The Tenant Allow/Block List, Advanced Delivery, and transport rules are powerful. Audit who can edit them, log changes, and review allow entries quarterly — an attacker who can add a TABL allow or an Advanced Delivery IP range can whitelist their own infrastructure.
- Protect the SecOps mailbox. A SecOps override mailbox receives live, unfiltered phish and malware. Isolate it, restrict access to the SOC, and never let its rules leak to general mail flow.
- Keep spoof and impersonation on for the whole population. These are your BEC and account-compromise defences; scope relief to specific pairs/senders, never turn the engines off org-wide.
- Feed verdicts to hunting. Safe Links click events, detection technologies, and quarantine actions are hunting signal — surface them in your SIEM and correlate, as in KQL Threat Hunting Playbooks: MITRE ATT&CK Mapping, UEBA, and Hunting Notebooks.
The security controls that also prevent tuning incidents — secure and low-friction pull the same way here:
| Control | Mechanism | Secures against | Also prevents |
|---|---|---|---|
| PIM for policy admins | Eligible, time-bound Security Admin | Standing over-privilege | Accidental broad policy changes |
| App-only automation auth | Certificate-based app | Stored admin credentials | Credential theft enabling bypass creation |
| Audited override surfaces | Unified audit log on TABL/Advanced Delivery | Attacker-added allow entries | Unaccountable, permanent bypasses |
| Admin submissions over manual allows | Submission-driven, time-boxed allows | Unaudited allow sprawl | Root cause masked only in your tenant |
| Isolated SecOps mailbox | Restricted access + no rule leakage | Live-malware exposure | Simulation/SecOps holes reaching general mail |
Cost & sizing
The bill here is licensing, not per-operation — the engines run on your existing plan, and configuration is free. What you are sizing is coverage against the plan you own:
- MDO Plan 1 (bundled with Microsoft 365 Business Premium) gives you Safe Attachments, Safe Links, and anti-phishing impersonation — the full configuration surface of this article. What you don’t get is deep investigation: only real-time detections, not full Threat Explorer, no Automated Investigation and Response (AIR), no attack simulation training, and no campaign views. Roughly ₹180–200 per user/month as a standalone add-on where sold separately.
- MDO Plan 2 (bundled with E5 or the E5 Security add-on) adds full Threat Explorer, AIR, attack simulation training, campaign views, and advanced hunting integration. Roughly ₹400–450 per user/month as a standalone add-on. This is what changes your triage workflow — Plan 1 configures identically but investigates blind.
- The configuration cost is zero. Every policy, rule, TABL entry, and Advanced Delivery override is free to create and change. The only “cost” of over-tuning is help-desk load (false positives) and risk (bypasses) — both operational, not billed.
Plan 1 vs Plan 2, and what each buys for tuning and triage:
| Capability | Plan 1 | Plan 2 | Why it matters to this article |
|---|---|---|---|
| Safe Attachments / Safe Links / anti-phishing config | Yes | Yes | Identical configuration surface on both plans |
| Threat Explorer (full) | No (real-time detections only) | Yes | The primary “why was this actioned?” tool for triage |
| Automated Investigation & Response (AIR) | No | Yes | Auto-remediation after a verdict |
| Attack simulation training | No | Yes | The human-risk side (separate article) |
| Campaign views + advanced hunting integration | No | Yes | Correlating a wave of related phish |
| Typical standalone add-on (INR/user/month) | ~₹180–200 | ~₹400–450 | Match your triage workflow to the plan |
A rough sizing rule: for 2,400 mailboxes on E5, MDO Plan 2 is already included, so the marginal cost of everything in this article is zero beyond the E5 you own — the investment is engineer time to tune, not licence spend. If you are on Business Premium (Plan 1), budget the triage workflow around real-time detections rather than full Explorer, and lean harder on admin submissions and message headers to answer “why was this actioned?”
Interview & exam questions
1. In what order does a message pass through EOP and MDO, and why does the order matter for tuning? Roughly: connection filter → anti-malware → Safe Attachments → transport rules → anti-spam/spoof → anti-phishing (impersonation/MI) → Safe Links at delivery, then Safe Links at click. It matters because the engine that actioned a message is the one whose stage it failed at, and an earlier stage can short-circuit later ones (malware never reaches anti-phishing). You tune the engine that fired, which you identify from the detection technology and headers.
2. A custom Safe Links policy at priority 0 isn’t applying to a group of users. Why, and how do you confirm? The users are almost certainly in a preset’s scope, and presets outrank all custom policies regardless of priority (the order is Strict preset → Standard preset → custom → Default). Confirm with Get-ATPProtectionPolicyRule/Get-EOPProtectionPolicyRule and check the preset’s SentToMemberOf/RecipientDomainIs. Fix by removing the users from the preset scope.
3. What is the difference between spoof intelligence and impersonation protection, and what’s the correct fix for a false positive from each? Spoof intelligence is about authentication — an unauthenticated visible From domain (SPF/DKIM/DMARC misalignment), confirmed by CompAuth=fail. Impersonation is about similarity — a different but look-alike user/domain. Fix a spoof false positive with a TABL spoof entry (one sending-infra/domain pair) and by fixing the partner’s mail auth; fix an impersonation false positive with a trusted sender/domain exclusion on the policy. Never disable the engine.
4. When do you use Safe Attachments Dynamic Delivery versus Block? Use Dynamic Delivery for human mailboxes: the message body is delivered immediately and the attachment is reattached after sandbox detonation, neutralising the latency. Use Block for shared or automation mailboxes that should never receive attachments, where holding until verdict (or dropping) is acceptable. Never leave the action on Monitor in production — it detonates and records but takes no protective action.
5. What does the click-time flow of Safe Links protect against that delivery-time scanning alone does not? Links that were clean at delivery and weaponised afterward. Safe Links rewrites the URL to a Microsoft wrapper; when the user clicks, the wrapper re-checks the destination’s current reputation, catching a URL an attacker armed an hour after the message was delivered. Delivery-time scanning (with DeliverMessageAfterScan) only protects the state at delivery.
6. Why is setting a transport rule to SCL -1 a dangerous way to fix a false positive? SCL -1 marks the message as non-spam and skips filtering for that path — which disables Safe Links, Safe Attachments, and spoof intelligence for every message matching the rule. An attacker who learns the whitelisted domain can spoof it and ride the bypass straight into inboxes. Use the Tenant Allow/Block List or Advanced Delivery instead, which relieve the specific false positive without opening a hole.
7. How do you correctly exempt a third-party phishing-simulation vendor and a SecOps analysis mailbox from filtering? Use the Advanced Delivery policy: a phishing-simulation override with the vendor’s sending IP ranges and simulation URLs, and a SecOps override for the analysis mailbox. This exempts exactly those flows without disabling filtering globally. A transport rule that skips filtering would create a real, exploitable bypass.
8. What does PhishThresholdLevel control, and why is 4 usually a mistake for the general population? It’s the phishing confidence slider (1 Standard → 4 Most aggressive) — how confident the ML must be before it acts. 4 acts on the widest set of borderline messages and reliably generates false positives on legitimate bulk and marketing mail. Use 1–2 for the general population and 3 for high-risk VIPs.
9. A partner’s legitimate mail is being quarantined as spoof. Walk through the correct remediation. Confirm it’s a spoof verdict (Threat Explorer detection technology “Spoof”; header CompAuth=fail). Add a time-boxed TABL spoof allow for the exact sending-infrastructure/spoofed-user pair to release the backlog. Then get the partner to publish you in their SPF and align DMARC so the message authenticates; once CompAuth=pass, remove the TABL allow. Never disable spoof intelligence or SCL -1 the domain.
10. What is the role of quarantine policies, and how do they reduce help-desk load? A quarantine policy decides what a user may do with a quarantined item — view, self-release, request release, or nothing. Mapping low-risk verdicts (spam, bulk) to a notification-enabled self-release policy lets users release their own newsletters without a ticket, while malware and high-confidence phish stay admin-only. This alignment removes the bulk of quarantine tickets without lowering protection.
11. Why prefer admin submissions over manually creating TABL allow entries? An admin submission both creates a time-boxed allow and sends the sample to Microsoft for reclassification — fixing the root cause for every tenant, not just masking it in yours. Hand-built allow entries only suppress the verdict locally and tend to accumulate as unaudited, sometimes -NoExpiration, permanent bypasses.
12. Which MDO plan is required for full Threat Explorer and attack simulation training, and does the plan change how you configure policies? Plan 2 (E5 / E5 Security) is required for full Threat Explorer, AIR, campaign views, and attack simulation training; Plan 1 gives only real-time detections. The plan does not change configuration — Safe Attachments, Safe Links, and anti-phishing are configured identically on both — it changes your ability to investigate and auto-remediate afterward.
These map to MS-102 (Microsoft 365 Administrator) — implement and manage Defender for Office 365, threat policies, and Exchange Online Protection — and to the SC-200 (Security Operations Analyst) angle of investigating and remediating email threats. A compact mapping for revision:
| Question theme | Primary cert | Objective area |
|---|---|---|
| Policy precedence, presets vs custom | MS-102 | Manage threat policies and security posture |
| Safe Attachments / Safe Links config | MS-102 | Implement Defender for Office 365 |
| Spoof vs impersonation, DMARC alignment | MS-102 / SC-200 | Email authentication; threat protection |
| TABL, Advanced Delivery, submissions | SC-200 | Remediate threats; manage allow/block |
| Threat Explorer / detection technology | SC-200 | Investigate email threats |
| Quarantine policies, user reporting | MS-102 | Manage quarantine and reporting |
Quick check
- A recipient is in the Strict preset’s scope, and you also created a custom Safe Links policy at priority 0 that should apply to them. Which one actually applies, and why?
- A legitimate partner’s invoices are being quarantined; the detection technology reads “Spoof” and the header shows
CompAuth=fail. What is the correct fix, and what are two things you must not do? - Which Safe Attachments action delivers the message body immediately and reattaches the file after detonation, and which mailbox class is it for?
- Your help desk is buried in “release my newsletter” tickets. What single change reduces this without lowering protection?
- True or false: to stop one spoof false positive, disabling spoof intelligence on the policy is an acceptable fix.
Answers
- The Strict preset applies. The fixed order is Strict preset → Standard preset → custom policies (by priority) → Default, and a recipient matches exactly one policy per type — the first in that order. Presets outrank all custom policies regardless of the custom policy’s priority, so the priority-0 custom policy never evaluates for that recipient.
- Add a time-boxed Tenant Allow/Block List spoof entry for the exact sending-infrastructure/spoofed-user pair, then get the partner to publish you in SPF and align DMARC (after which you remove the allow). You must not disable spoof intelligence (removes protection for the whole population) and must not add an SCL -1 transport rule (a total bypass for that path).
- Dynamic Delivery — the body is delivered immediately and the attachment is reattached after sandbox detonation. It’s for human mailboxes, where the latency of Block would be disruptive. (Block is for shared/automation mailboxes.)
- Map low-risk verdicts (bulk, spam) to a notification-enabled self-release quarantine policy (e.g.
DefaultFullAccessWithNotificationPolicy) so users release their own newsletters without a ticket, while keeping malware and high-confidence phish admin-only. - False. Disabling spoof intelligence removes spoof protection for the entire policy population. Scope the relief to the single pair with a TABL spoof allow and fix the partner’s DMARC alignment.
Glossary
- Exchange Online Protection (EOP) — the always-on anti-spam, anti-malware, connection-filtering, and spoof-intelligence layer every Exchange Online mailbox has; the floor MDO layers on top of.
- Defender for Office 365 (MDO) — the add-on (Plan 1/2) that adds Safe Attachments, Safe Links, and impersonation-aware anti-phishing on top of EOP.
- Safe Attachments — detonates unknown attachments in a sandbox before delivery; actions are Block, Dynamic Delivery, Replace, Monitor.
- Dynamic Delivery — a Safe Attachments action that delivers the message body immediately and reattaches the file once detonation completes.
- Safe Links — rewrites URLs to a Microsoft wrapper and re-checks the destination’s reputation at click time; catches links weaponised after delivery.
- Click-time protection — the moment Safe Links re-evaluates a URL’s reputation when the user clicks the wrapped link (distinct from delivery-time scanning).
- Anti-phishing policy — the MDO policy carrying user/domain impersonation, mailbox intelligence, spoof action, and the phishing confidence slider.
- Impersonation — protection against look-alike (similar but different) users or domains; fixed for false positives with trusted sender/domain exclusions.
- Mailbox intelligence — learns each user’s frequent-contact graph and flags impersonation of those contacts.
- Spoof intelligence — an EOP feature (actioned in the anti-phish policy) that flags messages whose visible
Fromdomain is unauthenticated; about authentication, not similarity. PhishThresholdLevel— the phishing confidence slider, 1 (Standard) to 4 (Most aggressive); higher is more aggressive and more false-positive-prone.- Composite authentication (
CompAuth) — the header result summarising SPF/DKIM/DMARC and spoof-intel evaluation;failsignals a spoof action fired. - Preset security policy (Standard/Strict) — Microsoft-maintained, auto-updating policies whose security settings can’t be edited (only scope, and impersonation config); always outrank custom policies.
- Policy vs rule — each protection has a policy (settings) and a rule (recipient conditions + priority) linked by name.
- Protection order / precedence — Strict preset → Standard preset → custom (by priority) → Default; a recipient matches exactly one policy per type.
- Tenant Allow/Block List (TABL) — the supported override surface for URL, file-hash, sender/domain, and spoof-pair allow/block entries; allows should be time-boxed.
- Advanced Delivery policy — the supported way to exempt phishing-simulation flows and SecOps mailboxes from filtering (never a transport rule).
- Admin submission — submitting a false positive/negative to Microsoft, which creates a time-boxed allow and triggers reclassification for all tenants.
- Quarantine policy — defines what a user may do with a quarantined item (view/release/request/none) and whether they get a notification.
- Advanced Delivery vs SCL -1 — the correct exemption surface vs the dangerous transport-rule bypass that disables filtering for a whole path.
Next steps
You can now tune all three MDO engines, respect precedence, and relieve false positives through supported surfaces. Build outward:
- Next: Operating the Defender for Office 365 Quarantine and Tenant Allow/Block List for SecOps — the day-two operations of the override surfaces this article introduced.
- Prerequisite: Enforcing Email Authentication for Exchange Online: SPF, DKIM, and DMARC From Monitoring to Reject — get mail auth right so spoof verdicts stop at the source.
- Related: Tuning Exchange Online Protection: Anti-Spam, Connection Filtering, and Quarantine Policies — the EOP floor MDO layers on, and where many “false positives” actually originate.
- Related: Running Defender for Office 365 Attack Simulation Training: Payloads, Automations, and Repeat Offenders — the human-risk side, and the Advanced Delivery exemptions that make simulations work.
- Related: KQL Threat Hunting Playbooks: MITRE ATT&CK Mapping, UEBA, and Hunting Notebooks — turn Safe Links clicks and detection technologies into hunting signal.