1. Overview and Context
Zero-Hour Auto Purge (ZAP) is a post-delivery remediation mechanism built into Exchange Online Protection (EOP), enabling retroactive mitigation of malware, phishing, and spam threats after messages have entered cloud mailboxes. This functionality arises in response to two critical realities:
-
- Evolving threat intelligence: New spam/malware signatures and heuristics are continuously updated, potentially allowing earlier evasive threats to be detected post-delivery.
- Content weaponization: Entities that were initially benign or undetected may morph into malicious payloads after arrival.
ZAP keeps an eye on the past—scanning for threats in mail that has already landed in mailboxes—and automatically neutralizes risks without notifying end users.
Importantly, ZAP operates strictly within cloud-hosted Exchange Online environments and does not apply to on-premises mailboxes even if protected by standalone EOP.
2. Threat Classification and ZAP Response Mapping
ZAP handles three threat categories differently, based on post-delivery detection and policy configuration:
2.1 Malware
-
- Post-delivery detection: When malware is discovered in read or unread messages, ZAP quarantines the message.
- Quarantine policy: By default, messages are moved to the AdminOnlyAccessPolicy—admins can manage them; users cannot release the message. If policy allows, users can request release rather than self-release.
2.2 Phishing (non-high confidence)
-
- Configurable actions—based on anti-spam policy verdict for phishing:
-
- No action (e.g., adding X-header, subject prepend, redirect, delete): ZAP takes no action.
- Move to Junk Email: ZAP relocates the message to the Junk Email folder —typically the default action under most default and custom anti-spam policies.
- Quarantine: ZAP overrides and quarantines the message—default for Standard and Strict preset policies and custom Defender Portal anti-spam policies.
-
- Configurable actions—based on anti-spam policy verdict for phishing:
2.3 High-Confidence Phishing
-
- ZAP immediately quarantines messages identified as high-confidence phishing. Default quarantine policy is AdminOnlyAccess; user release is not permitted, though users can request release if the policy so allows.
2.4 Spam (and High-Confidence Spam)
-
- Unread messages only: ZAP acts only on unread spam/high-confidence spam.
- Possible actions:
-
- No action: e.g., Add X-header, etc.—ZAP ignores message.
- Move to Junk Email: Default—message is relocated to Junk Email folder.
- Quarantine: If configured, ZAP moves it to quarantine; users may have limited abilities to manage based on policies.
-
3. Enabling and Configuring ZAP via Portal and PowerShell
ZAP is enabled by default across anti-malware and anti-spam policies. Administrators have granular control:
-
- Anti-malware policies:
-
- Option Enable zero-hour auto purge for malware (ZAP for malware) is turned ON by default.
- Admins can select quarantine policy and decide whether admins receive notifications for internal or external senders.
-
- Anti-spam policies:
-
- Options for Enable ZAP for phishing (PhishZapEnabled) and ZAP for spam (SpamZapEnabled) are also enabled by default.
- Admins may disable these if needed through policy edits in the Defender portal or via PowerShell (e.g.,
Set-HostedContentFilterPolicy
).
-
- Anti-malware policies:
Recommended configurations—Standard and Strict preset policies—retain ZAP enabled across malware, phishing, and spam.
4. Monitoring ZAP Activity — Reporting and Auditing
Effective operational oversight requires monitoring ZAP’s retroactive actions:
-
- Mailflow status reports:
-
- Access via Microsoft 365 Defender → Reports → Email & collaboration → Mailflow status summary.
- Filter for Additional action = ZAP to identify affected messages, with details on original and latest delivery locations. These reports are generally available for the last 90 days.
-
- Threat Explorer:
-
- Search for ZAP actions to see granular details of message attributes and actions taken.
-
- Administrative Quarantine Management:
-
- Admins can view, release, or delete quarantined items via Defender Portal or Exchange Online PowerShell.
- Access is controlled through granular RBAC roles such as Quarantine Administrator or Security Administrator. Actions are audited for compliance.
-
- Mailflow status reports:
5. ZAP in Microsoft Teams (Extended Protection)
Beyond email, ZAP extends into Microsoft Teams (available under Microsoft 365 E5 or Defender for Office 365 Plan 2):
-
- Scope:
-
- ZAP monitors internal Teams messages (chat, shared, standard channels). External messages are not supported.
- Detection includes malware and high-confidence phishing.
-
- Action:
-
- Suspicious messages are blocked and quarantined, typically via AdminOnlyAccess quarantine policy. The block happens immediately and reverse–scans may occur up to 48 hours post-delivery.
-
- Configuration:
-
- Enabled by default post-August 2023 for eligible organizations. Administrators may disable it via Defender portal (
Settings → Email & collaboration → Microsoft Teams protection
) or via PowerShell using cmdlets:-
Get-TeamsProtectionPolicy
,Set-TeamsProtectionPolicy
Get-TeamsProtectionPolicyRule
,Set-TeamsProtectionPolicyRule
to configure exclusions for recipients or users.
-
- Enabled by default post-August 2023 for eligible organizations. Administrators may disable it via Defender portal (
-
- Administrative Exclusions:
-
- Exclusions are defined at the recipient level, not sender. If recipients in a chat are excluded, ZAP may not block the message—even if flagged.
-
- Scope:
6. Summary Table: Threat Type → ZAP Behavior
Threat Type | Detection Time | ZAP Action | Eligibility |
---|---|---|---|
Malware (email) | Post-delivery | Quarantine (AdminOnlyAccess) | All cloud mailboxes, default enabled |
Non-HC Phishing (email) | Post-delivery | Move to Junk or Quarantine based on policy | Configurable per anti-spam policy |
High-Confidence Phishing | Post-delivery | Quarantine (AdminOnlyAccess) | Default enabled, user request possible |
Spam / HC Spam (email) | Only if unread | Move to Junk or Quarantine based on policy | SpamZapEnabled toggle, default enabled |
Malware (Teams) | Post-delivery (≤ 48 h) | Block & Quarantine | Teams Plan 2/E5, internal chats only |
HC Phishing (Teams) | Post-delivery (≤ 48 h) | Block & Quarantine | Teams Plan 2/E5, internal chats only |
Zero-Hour Auto Purge in Exchange Online serves as a strategic backstop—extending security reaction time and scope to threats that evade initial scans or manifest post-delivery. Its out-of-the-box enablement underscores Microsoft’s “Secure by Default” philosophy, while policy-level tuning enables administrators to calibrate actions for workload flow, false positive tolerance, and user autonomy.
Rigorous monitoring via Mailflow, Threat Explorer, and quarantine logs ensures visibility and accountability, key to an enterprise-grade security posture.
PowerShell Configuration & Operational Cookbook for ZAP (Exchange Online)
1. Connect
# Requires ExchangeOnlineManagement module
Connect-ExchangeOnline -UserPrincipalName admin@contoso.com
2. Inspect current ZAP posture
# Anti-spam (content filter) ZAP status
Get-HostedContentFilterPolicy |
Select-Object Name, SpamZapEnabled, PhishZapEnabled,
HighConfidenceSpamAction, HighConfidencePhishAction,
SpamAction, PhishSpamAction,
SpamQuarantineTag, HighConfidenceSpamQuarantineTag,
PhishQuarantineTag, HighConfidencePhishQuarantineTag |
Format-List
# Anti-malware ZAP status
Get-MalwareFilterPolicy |
Select-Object Name, ZapEnabled, QuarantineTag, EnableInternalSenderAdminNotifications,
EnableExternalSenderAdminNotifications |
Format-List
3. Toggle ZAP (on/off) per threat family
# Enable ZAP for phishing and spam in the Default anti-spam policy
Set-HostedContentFilterPolicy -Identity "Default" -PhishZapEnabled $true -SpamZapEnabled $true
# Disable (if you must) — not recommended
Set-HostedContentFilterPolicy -Identity "Default" -PhishZapEnabled $false -SpamZapEnabled $false
# Enable ZAP for malware in the Default anti-malware policy
Set-MalwareFilterPolicy -Identity "Default" -ZapEnabled $true
4. Enforce quarantine on bad verdicts (and pick which quarantine policy applies)
Tip: Create your custom quarantine policy in the portal first (e.g.,
FullAccessWithNotify
), then reference it via the*QuarantineTag
parameters below. Defaults likeAdminOnlyAccessPolicy
andDefaultFullAccessWithNotificationPolicy
are also valid tags.
# Phishing → Quarantine + pick quarantine policy
Set-HostedContentFilterPolicy -Identity "Default" `
-PhishSpamAction Quarantine `
-PhishQuarantineTag "FullAccessWithNotify"
# High-confidence phishing → Quarantine (strongly recommended) + strict policy
Set-HostedContentFilterPolicy -Identity "Default" `
-HighConfidencePhishAction Quarantine `
-HighConfidencePhishQuarantineTag "AdminOnlyAccessPolicy"
# Spam / High-confidence spam → move to Junk or Quarantine
# (Example: quarantine both and notify users via a permissive quarantine policy)
Set-HostedContentFilterPolicy -Identity "Default" `
-SpamAction Quarantine `
-SpamQuarantineTag "DefaultFullAccessWithNotificationPolicy" `
-HighConfidenceSpamAction Quarantine `
-HighConfidenceSpamQuarantineTag "DefaultFullAccessWithNotificationPolicy"
# Optional: tune quarantine retention (in days; spam-only scope)
Set-HostedContentFilterPolicy -Identity "Default" -QuarantineRetentionPeriod 15
5. Malware policy hygiene (notifications, file filters, quarantine target)
# Use ZAP for malware and send admin notifications
Set-MalwareFilterPolicy -Identity "Default" `
-ZapEnabled $true `
-EnableInternalSenderAdminNotifications $true `
-InternalSenderAdminAddress "soc@contoso.com" `
-EnableExternalSenderAdminNotifications $true `
-ExternalSenderAdminAddress "soc@contoso.com" `
-QuarantineTag "AdminOnlyAccessPolicy"
# (Optional) Harden attachment filtering at the malware layer
Set-MalwareFilterPolicy -Identity "Default" `
-EnableFileFilter $true `
-FileTypeAction Reject `
-FileTypes "ace","iso","img","js","vbs"
6. Scope a custom anti-spam policy (target a pilot group)
# Create a stricter policy
New-HostedContentFilterPolicy -Name "Contoso-Strict" `
-SpamZapEnabled $true -PhishZapEnabled $true `
-PhishSpamAction Quarantine `
-HighConfidencePhishAction Quarantine `
-SpamAction Quarantine `
-HighConfidenceSpamAction Quarantine `
-PhishQuarantineTag "FullAccessWithNotify" `
-HighConfidencePhishQuarantineTag "AdminOnlyAccessPolicy" `
-SpamQuarantineTag "DefaultFullAccessWithNotificationPolicy" `
-HighConfidenceSpamQuarantineTag "DefaultFullAccessWithNotificationPolicy"
# Assign it to a group with higher priority than Default
New-HostedContentFilterRule -Name "Contoso-Strict-Rule" `
-HostedContentFilterPolicy "Contoso-Strict" `
-RecipientDomainIs @("contoso.com") `
-ExceptIfRecipientAddressContainsWords @() `
-Priority 0 `
-SentToMemberOf "SEC-ZAP-Pilot"
7. Day-2 Ops: find, export, and (carefully) release ZAP’d items
# List quarantined messages (all sources) from the last 48 hours
$since = (Get-Date).AddDays(-2)
Get-QuarantineMessage -ReceivedTimeStart $since |
Select-Object Identity, ReceivedTime, PolicyType, QuarantineTypes,
Subject, SenderAddress, RecipientAddress, ReleaseStatus |
Sort-Object ReceivedTime -Descending
# Focus on messages quarantined by anti-spam vs anti-malware
Get-QuarantineMessage -PolicyTypes HostedContentFilterPolicy -ReceivedTimeStart $since
Get-QuarantineMessage -PolicyTypes AntiMalwarePolicy -ReceivedTimeStart $since
# Export a CSV for review
Get-QuarantineMessage -ReceivedTimeStart $since |
Select-Object Identity, ReceivedTime, PolicyType, Subject, SenderAddress, RecipientAddress, ReleaseStatus |
Export-Csv .\Quarantine_Last48h.csv -NoTypeInformation -Encoding UTF8
# Preview details for one message
$q = Get-QuarantineMessage -ReceivedTimeStart $since | Select-Object -First 1
$q | Format-List *
# Release a single message to original recipients (use only after validation)
Release-QuarantineMessage -Identity $q.Identity -ReleaseToAll
# Bulk release from a vetted CSV of Identities
Import-Csv .\to-release.csv | ForEach-Object {
Release-QuarantineMessage -Identity $_.Identity -ReleaseToAll
}
8. Audit & threat intel breadcrumbs (advanced)
# Pull Threat Intelligence / email detection events (last 7 days) for offline triage
$start=(Get-Date).AddDays(-7); $end=Get-Date
$ti = Search-UnifiedAuditLog -StartDate $start -EndDate $end -RecordType ThreatIntelligence -SessionCommand ReturnLargeSet
$ti | Export-Csv .\UnifiedAudit_ThreatIntel_7d.csv -NoTypeInformation -Encoding UTF8
9. Quick rollback / reset snippets
# Roll back a custom HostedContentFilterPolicy to "move to Junk"
Set-HostedContentFilterPolicy -Identity "Contoso-Strict" `
-SpamAction MoveToJmf `
-HighConfidenceSpamAction MoveToJmf `
-PhishSpamAction MoveToJmf `
-HighConfidencePhishAction Quarantine # keep HC Phish strict
# Re-point quarantine tags back to the default notification policy
Set-HostedContentFilterPolicy -Identity "Contoso-Strict" `
-SpamQuarantineTag "DefaultFullAccessWithNotificationPolicy" `
-HighConfidenceSpamQuarantineTag "DefaultFullAccessWithNotificationPolicy" `
-PhishQuarantineTag "DefaultFullAccessWithNotificationPolicy"
Notes for production
-
- Keep ZAP enabled everywhere; customize actions (Junk vs Quarantine) and quarantine policies to tune user experience and risk tolerance.
- Prefer strict quarantine for high-confidence phishing; use AdminOnly for the most dangerous verdicts.
- Use scoped pilot policies (rules targeting groups) to validate changes before broad rollout.
- Build a simple daily export of
Get-QuarantineMessage
results and ingest into your SOC tooling for trend analysis. - Treat bulk releases as high-risk operations — require a second set of eyes and preserve the CSV/approval trail.