9.5 Zero-Hour Auto Purge (ZAP)

90 minutes · Module 9

Zero-Hour Auto Purge (ZAP)

By the end of this subsection, you will understand how ZAP works as post-delivery remediation, know the gap it creates and how to monitor it, and track ZAP actions with KQL.

How ZAP works

ZAP is the safety net. When an email passes all scanning at delivery but is later identified as malicious (new threat intelligence, updated ML model, manual submission analysis), ZAP retroactively removes or moves it from the user’s mailbox.

The ZAP sequence:

  1. Email delivered to inbox (passes all scanning at delivery time)
  2. Hours later: Microsoft threat intelligence updates the URL/file verdict to malicious
  3. ZAP checks all delivered emails against the updated verdict
  4. ZAP takes action: moves to Junk, soft deletes, or replaces the email

ZAP actions

ActionWhat happensWhen used
Move to JunkEmail moved to Junk folderSpam verdict update
Soft deleteEmail moved to Deleted Items, then to Recoverable ItemsPhishing or malware verdict update
QuarantineEmail moved to quarantineHigh-confidence phishing verdict

The ZAP gap

ZAP is not instant. In Module 14, ZAP removed 4 of 23 phishing emails — but only 23 minutes after delivery. During those 23 minutes, 7 users clicked the link and 5 reached the phishing proxy. This is the ZAP gap: the time between email delivery and ZAP action.

The ZAP gap is your exposure window

A 23-minute gap means 23 minutes where users can interact with the phishing email. Click rates for phishing emails peak in the first 5-10 minutes after delivery. ZAP at 23 minutes catches some users (those who had not yet opened the email) but misses the fast clickers. Your goal is to minimize the gap through better initial detection (anti-phishing thresholds, Safe Links) and faster verdict updates (first contact safety tips, user reporting).

Monitoring ZAP with KQL

1
2
3
4
5
6
7
8
9
EmailPostDeliveryEvents
| where TimeGenerated > ago(30d)
| where ActionType in ("ZAP", "ZapCompleted")
| extend ZapAction = tostring(parse_json(ActionDetails).action)
| summarize
    ZapCount = count(),
    AvgDelayMinutes = round(avg(datetime_diff('minute', TimeGenerated, DeliveryTime)), 0)
    by ZapAction, bin(TimeGenerated, 1d)
| sort by TimeGenerated desc
Expected Output
ZapActionDateZapCountAvgDelayMinutes
SoftDeleteMar 20834
MoveToJunkMar 201218
SoftDeleteMar 19447
What to look for: Average ZAP delay of 34-47 minutes for soft deletes means nearly an hour of exposure for phishing emails. This is Microsoft's verdict update speed, not something you can configure. Your mitigation: faster initial detection (aggressive anti-phishing thresholds), user awareness (first contact safety tips), and click-through prevention (Safe Links block mode).

ZAP configuration and interaction with other controls

ZAP is enabled by default for all Exchange Online mailboxes. It is not a policy you configure per se — but its behavior is affected by other configurations:

FactorImpact on ZAP
Anti-phishing policy actionIf your policy delivers phishing to Junk (not quarantine), ZAP moves the email from Inbox to Junk. If policy quarantines, ZAP moves to quarantine.
Transport rulesEmails that match a transport rule “stop processing” condition bypass ZAP — the transport rule takes precedence
User-moved emailsIf a user moves the email to a custom folder, ZAP behavior varies — it may not be able to act on emails in certain folder types
Mailbox on litigation holdZAP removes the email from the user’s view but preserves it in Recoverable Items for compliance
ZAP is a complement to initial detection, not a replacement

If your initial detection catches 95% of phishing at delivery, ZAP catches some of the remaining 5% post-delivery. But ZAP cannot catch 100% of what initial detection misses — its effectiveness depends on when Microsoft's threat intelligence updates the verdict. The strongest email protection minimizes reliance on ZAP by maximizing initial detection: aggressive thresholds, comprehensive Safe Links, and transport rules.

The three controls work in sequence:

  1. Initial detection blocks emails at delivery (best outcome — user never sees the email)
  2. Safe Links protects at click time (user received the email but the URL is scanned when clicked)
  3. ZAP removes post-delivery (user received and potentially read the email, but it is removed before further interaction)

The Module 14 timeline illustrates this: initial detection caught 0 of 23 (CAPTCHAed URL). Safe Links warned 7 clickers (5 clicked through). ZAP removed 4 after 23 minutes. The 19 that remained in inboxes were the exposure window. Each control layer reduces the exposure, but none alone is sufficient.

ZAP effectiveness over time

Track ZAP’s contribution to your overall email security over 30 days:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
EmailPostDeliveryEvents
| where TimeGenerated > ago(30d)
| where ActionType has "ZAP"
| summarize
    TotalZAP = count(),
    PhishZAP = countif(ActionTrigger has "Phish"),
    MalwareZAP = countif(ActionTrigger has "Malware"),
    SpamZAP = countif(ActionTrigger has "Spam")
    by bin(TimeGenerated, 7d)
| sort by TimeGenerated asc
Expected Output
WeekTotalZAPPhishZAPMalwareZAPSpamZAP
Week 1238312
Week 2185211
Week 34731115
Week 414419
What to look for: Week 3's spike (31 phishing ZAPs) indicates a phishing campaign that bypassed initial detection but was caught post-delivery. Cross-reference with EmailEvents for that week to identify the campaign. A consistently high PhishZAP count suggests your initial anti-phishing detection needs tuning — ZAP is catching what the front-line filters should have caught.

Required role and blast radius

Required role: Security Administrator (to view ZAP configuration). ZAP itself is automatic — no manual configuration required.


ZAP timing and the detection gap

ZAP does not run at delivery time. It runs when the threat verdict changes — which can be minutes to hours after delivery.

The timeline:

T=0: Email delivered to inbox. Verdict: clean. T=5 minutes: Microsoft’s backend analysis updates the URL reputation (the URL was submitted by another tenant, or the sandbox completed a delayed detonation). New verdict: phishing. T=5-30 minutes: ZAP triggers. The email is moved from the inbox to quarantine (for phishing) or junk (for spam).

The gap: Between T=0 and T=5-30 minutes, the email sits in the user’s inbox. If the user opens and clicks during this window: the attack succeeds despite ZAP. This is why Safe Links time-of-click scanning and anti-phishing policies are your primary defences — ZAP is the safety net, not the primary control.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
// ZAP effectiveness monitoring  how many emails were removed post-delivery?
EmailPostDeliveryEvents
| where TimeGenerated > ago(30d)
| where ActionType == "ZAP"
| extend ZapAction = tostring(parse_json(tostring(AdditionalFields)).Action)
| extend ThreatType = tostring(parse_json(tostring(AdditionalFields)).DeliveryAction)
| summarize
    TotalZAPs = count(),
    PhishingZAPs = countif(ZapAction has "Phish"),
    MalwareZAPs = countif(ZapAction has "Malware"),
    SpamZAPs = countif(ZapAction has "Spam")
    by bin(TimeGenerated, 7d)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
// ZAP timing analysis  how long between delivery and removal?
let Deliveries = EmailEvents
| where TimeGenerated > ago(30d)
| where DeliveryAction == "Delivered"
| project DeliveryTime = TimeGenerated, NetworkMessageId;
EmailPostDeliveryEvents
| where TimeGenerated > ago(30d)
| where ActionType == "ZAP"
| project ZapTime = TimeGenerated, NetworkMessageId
| join kind=inner Deliveries on NetworkMessageId
| extend GapMinutes = datetime_diff('minute', ZapTime, DeliveryTime)
| summarize
    AvgGapMinutes = avg(GapMinutes),
    MedianGapMinutes = percentile(GapMinutes, 50),
    P95GapMinutes = percentile(GapMinutes, 95),
    MaxGapMinutes = max(GapMinutes)

What to look for: If the average ZAP gap is under 15 minutes: acceptable. If P95 exceeds 60 minutes: a significant percentage of emails sit in inboxes for over an hour before ZAP removes them — during which users may click. Report this metric in your monthly security dashboard.

ZAP for Teams and SharePoint

ZAP for email has been available since EOP. ZAP-like capabilities for Teams messages and SharePoint files are being extended — check the current Microsoft roadmap for availability. When available: enable immediately. The same gap that exists for email (user clicks before ZAP) exists for Teams (user clicks a URL shared in chat before the message is removed).

What ZAP cannot do

ZAP removes the email from the mailbox. It cannot: undo a click (if the user already clicked the URL), recover credentials (if the user entered them on the phishing page), revoke tokens (if the AiTM proxy captured them), or remove inbox rules (if the attacker created persistence).

This is why ZAP is the last layer, not the only layer. Module 12 Wave 1: 23 phishing emails delivered. ZAP removed 4 after 23 minutes. 19 remained in inboxes. 6 users clicked before ZAP acted. The containment was not ZAP — it was the investigation and response that followed.

Compliance mapping

NIST CSF: DE.CM-4 (Malicious code detected), RS.MI-2 (Incidents are mitigated). ISO 27001: A.8.7 (Protection against malware). SOC 2: CC7.4 (Detected incidents are communicated). ZAP is a post-delivery remediation control that demonstrates automated response capability.


ZAP configuration and policy

ZAP is enabled by default in all Exchange Online tenants. There is limited configuration — but what exists matters:

Anti-phishing policy ZAP setting: Ensure “Enable Zero-hour auto purge for phishing messages” is ON. Navigate to: Defender → Policies → Anti-phishing → default policy → Actions → Zero-hour auto purge. Separately verify: “Enable Zero-hour auto purge for spam messages” is ON (in the anti-spam policy).

ZAP actions by threat type:

Threat typeZAP actionDestination
PhishingMove to quarantineAdmin quarantine (user cannot release without admin approval)
High confidence phishingMove to quarantineAdmin quarantine
SpamMove to JunkUser’s Junk folder
High confidence spamMove to quarantineAdmin quarantine
MalwareMove to quarantineAdmin quarantine

Note: ZAP cannot remove email from the Deleted Items folder. If the user has already read and deleted the email, ZAP does not affect it. ZAP also does not remove email from items the user has moved to a non-standard folder (if the user manually moved the email to a “Saved” folder before ZAP triggered).

ZAP and shared mailboxes

ZAP operates on individual mailboxes. For shared mailboxes (used by teams — e.g., finance@northgateeng.com, support@northgateeng.com): ZAP removes the email from the shared mailbox. All team members who had access see the email disappear. If any team member already opened or clicked: ZAP does not undo that interaction.

Operational note: Shared mailboxes used by finance teams are high-value BEC targets (Module 13). ZAP for these mailboxes is critical — a phishing email sitting in a shared mailbox is accessible to multiple people, multiplying the click probability. Verify ZAP is enabled for shared mailboxes (it should be by default, but confirm in your tenant).

1
2
3
4
5
6
7
// ZAP events for shared mailboxes  are they being protected?
EmailPostDeliveryEvents
| where TimeGenerated > ago(30d)
| where ActionType == "ZAP"
| where RecipientEmailAddress in ("finance@northgateeng.com",
    "support@northgateeng.com", "hr@northgateeng.com")
| summarize ZapCount = count() by RecipientEmailAddress, bin(TimeGenerated, 7d)

If shared mailboxes show zero ZAP events: either no phishing emails were delivered to them (good), or ZAP is not processing shared mailboxes in your tenant (investigate).

ZAP false positives and user communication

ZAP occasionally removes legitimate email — a message initially delivered as clean is reclassified as spam or phishing by updated ML models. The user sees the email disappear from their inbox without explanation.

Handling complaints: “I had an email from [sender] and it disappeared.” Check quarantine: Defender → Review → Quarantine. If the email is there: review the classification. If false positive: release the email and report to Microsoft (improves future classification). If true positive: explain to the user that the email was identified as malicious after delivery.

Proactive communication: Include in your security awareness programme: “Our email system automatically removes emails that are identified as threats after delivery. If an expected email disappears, check your Junk folder first, then contact IT security to review the quarantine.”


ZAP in the incident response workflow

ZAP is often the first indicator that a phishing campaign is in progress. When ZAP removes multiple emails from multiple users within a short window: something triggered a verdict change across the campaign.

Detection pattern: Create a Sentinel analytics rule that alerts when ZAP removes more than 10 emails in a 1-hour window:

1
2
3
4
5
6
7
8
// Analytics rule: ZAP campaign detection
EmailPostDeliveryEvents
| where TimeGenerated > ago(1h)
| where ActionType == "ZAP"
| summarize ZAPCount = count(), AffectedUsers = dcount(RecipientEmailAddress),
    Subjects = make_set(Subject, 5)
    by bin(TimeGenerated, 1h)
| where ZAPCount > 10

Why this matters: If ZAP removes 15 emails in an hour, those emails were delivered to 15 inboxes and sat there until the verdict changed. Some users may have already clicked. The ZAP alert should trigger: a UrlClickEvents check (did anyone click before ZAP?), a sign-in investigation for clickers, and a review of why the emails passed initial scanning (what should be tuned?).

This ZAP-triggered investigation pattern connects Module 9 (email protection) to Module 12 (AiTM investigation) — ZAP cleaned up the emails, but the investigation must determine whether any users were compromised during the delivery-to-ZAP window.

ZAP and litigation holds

If a mailbox is on litigation hold (Module 13.7, Module 16.5), ZAP still moves the email to quarantine — but the litigation hold preserves a copy. The email is removed from the user’s view (the security objective) but remains discoverable for legal purposes (the compliance objective). Both requirements are satisfied simultaneously.

This is important during BEC investigations where you need to: remove the evidence of the phishing email from the user’s inbox (so they do not interact with it further), AND preserve the email for law enforcement evidence (so the original headers and content are available for forensic analysis). ZAP + litigation hold achieves both.

Try it yourself

In your test tenant: verify ZAP is enabled for both phishing and spam in your anti-phishing and anti-spam policies. Then run the ZAP timing analysis query from this subsection against the last 30 days. What is your average ZAP gap? If you have ZAP events: examine the timing distribution — are most ZAP actions within 15 minutes, or are some taking hours? This metric belongs in your monthly email protection report.

ZAP should be enabled in both policies (default: yes). The timing analysis in a lab may show zero ZAP events (no threats to remediate). In production: average gap should be under 15 minutes. P95 under 60 minutes. If P95 exceeds 60 minutes: some emails are sitting in inboxes for over an hour before ZAP acts — this is the window where users click.

Try it yourself

ZAP removed a phishing email from 4 mailboxes but the email was already read by 3 of those 4 users. What should you do for the 3 users who read it?

ZAP removed the email but cannot undo what the user already did. For each user who read the email:

1. Check UrlClickEvents: Did they click a link in the email?

2. Check SigninLogs: If they clicked a phishing link, check for suspicious sign-in activity (token replay, new IP, new location).

3. If credentials may have been entered: Revoke sessions, reset password, force MFA re-registration — the containment sequence from Module 14.7.

ZAP handling the email is not the end of the investigation. It is the start — ZAP tells you the email was malicious, but you must determine whether any user acted on it before removal.

Check your understanding

1. ZAP removed 4 of 23 phishing emails. Why not all 23?

ZAP only removes emails that are still in the mailbox when the verdict updates. The 19 emails not removed had already been read, moved, or deleted by users before ZAP ran. Additionally, ZAP respects certain mailbox rules — if a user moved the email to a custom folder, ZAP's behavior depends on the folder type.
ZAP has a 4-email limit
ZAP was misconfigured