Skip to content

Commit 8d00863

Browse files
authored
SecOps - 41059 - EDR in block mode is enabled when Microsoft Defender Antivirus is not the primary antivirus (#1389)
[Spec-41059](https://github.com/microsoft/ztspecs/blob/main/specs/secops/41059.md) [Issue #908](microsoft/ztspecs#908)
2 parents 755b900 + cd7f090 commit 8d00863

2 files changed

Lines changed: 230 additions & 0 deletions

File tree

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
EDR in block mode adds Microsoft Defender for Endpoint blocking when Microsoft Defender Antivirus is not the primary antivirus and is running in passive mode. Microsoft documents that it provides added protection from malicious artifacts in this scenario and is available in Defender for Endpoint Plan 2. This matters because threat actors can evade or outpace a third-party antivirus product, then continue from execution into defense evasion, credential access, lateral movement, and impact while defenders investigate. With EDR in block mode disabled, EDR can still detect activity, but malicious artifacts that another antivirus missed might not be actively remediated by Microsoft Defender for Endpoint. The feature does not restore all capabilities that require Defender Antivirus active mode; Microsoft notes that real-time protection, network protection, attack surface reduction rules, and indicators have active-mode dependencies. It is still a critical safety net for tenants that rely on non-Microsoft antivirus. This check uses the pinned MDATP Secure Score control `scid_2004`.
2+
3+
**Remediation action**
4+
5+
- [Endpoint detection and response in block mode](https://learn.microsoft.com/en-us/defender-endpoint/edr-in-block-mode)
6+
- [Frequently asked questions on EDR in block mode](https://learn.microsoft.com/en-us/defender-endpoint/edr-in-block-mode#frequently-asked-questions)
7+
- [Microsoft Defender Antivirus compatibility](https://learn.microsoft.com/en-us/defender-endpoint/microsoft-defender-antivirus-compatibility)
8+
9+
<!--- Results --->
10+
%TestResult%
Lines changed: 220 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,220 @@
1+
<#
2+
.SYNOPSIS
3+
EDR in block mode is enabled when Microsoft Defender Antivirus is not the primary antivirus.
4+
5+
.DESCRIPTION
6+
Validates the Microsoft Defender for Endpoint "Enable EDR in block mode" Secure Score
7+
recommendation via Microsoft Secure Score.
8+
9+
EDR in block mode adds Microsoft Defender for Endpoint blocking when Microsoft Defender
10+
Antivirus is running in passive mode alongside a non-Microsoft antivirus solution.
11+
Malicious artifacts that the third-party antivirus misses may not be remediated without it.
12+
13+
The check reads the Secure Score control profile for scid_2004 and the latest per-control
14+
score snapshot, then returns:
15+
Pass – EDR in block mode is enabled.
16+
Fail – EDR in block mode is disabled or the Secure Score control is ignored.
17+
Investigate – The control profile or Secure Score snapshot could not be located.
18+
Investigate – Microsoft Graph returned HTTP 401 or 403 (insufficient permissions).
19+
20+
.NOTES
21+
Test ID: 41059
22+
Workshop Task: SECOPS-059
23+
Pillar: SecOps
24+
Category: Endpoint threat protection
25+
Risk Level: High
26+
Supported Clouds: Global, USGov, USGovDoD
27+
Required Permission: SecurityEvents.Read.All (Application or Delegated)
28+
#>
29+
30+
function Test-Assessment-41059 {
31+
[ZtTest(
32+
Category = 'Endpoint threat protection',
33+
CompatibleLicense = ('WINDEFATP'),
34+
ImplementationCost = 'Low',
35+
Pillar = 'SecOps',
36+
RiskLevel = 'High',
37+
Service = ('Graph'),
38+
SfiPillar = 'Monitor and detect cyberthreats',
39+
TenantType = ('Workforce'),
40+
TestId = 41059,
41+
Title = 'EDR in block mode is enabled when Microsoft Defender Antivirus is not the primary antivirus',
42+
UserImpact = 'Low'
43+
)]
44+
[CmdletBinding()]
45+
param()
46+
47+
#region Data Collection
48+
49+
Write-PSFMessage '🟦 Start' -Tag Test -Level VeryVerbose
50+
$activity = 'Checking EDR in block mode Secure Score control'
51+
$controlId = 'scid_2004'
52+
Write-ZtProgress -Activity $activity -Status 'Retrieving EDR in block mode Secure Score control profile'
53+
54+
# Q1 – Retrieve the pinned MDATP "Enable EDR in block mode" control profile.
55+
# An empty result set indicates the profile is absent from this tenant's Secure Score.
56+
$controlProfile = $null
57+
$errorMsgQ1 = $null
58+
$httpStatusQ1 = $null
59+
60+
try {
61+
$profileResults = Invoke-ZtGraphRequest -RelativeUri 'security/secureScoreControlProfiles' -Filter "service eq 'MDATP' and id eq '$controlId'" -ApiVersion beta -ErrorAction Stop
62+
$controlProfile = $profileResults | Select-Object -First 1
63+
}
64+
catch {
65+
$errorMsgQ1 = $_
66+
$httpStatusQ1 = Get-ZtHttpStatusCode -ErrorRecord $_
67+
Write-PSFMessage "Failed to retrieve EDR in block mode control profile: $errorMsgQ1" -Level Warning
68+
}
69+
70+
# Q2 – Retrieve the most recent Secure Score snapshot (only if Q1 succeeded).
71+
$latestSecureScore = $null
72+
$errorMsgQ2 = $null
73+
74+
if ($null -ne $controlProfile) {
75+
Write-ZtProgress -Activity $activity -Status 'Retrieving latest Microsoft Secure Score'
76+
try {
77+
$scoreResponse = Invoke-ZtGraphRequest -RelativeUri 'security/secureScores' -Top 1 -ApiVersion beta -DisablePaging -ErrorAction Stop
78+
$latestSecureScore = $scoreResponse.value | Select-Object -First 1
79+
}
80+
catch {
81+
$errorMsgQ2 = $_
82+
Write-PSFMessage "Failed to retrieve Secure Score snapshot: $errorMsgQ2" -Level Warning
83+
}
84+
}
85+
86+
#endregion Data Collection
87+
88+
#region Assessment Logic
89+
90+
$passed = $false
91+
$customStatus = $null
92+
93+
# ── Q1 failed: 401/403, unexpected error, or missing profile → Investigate ──
94+
if ($null -eq $controlProfile) {
95+
if ($httpStatusQ1 -in @(401, 403)) {
96+
$investigateReason = 'The **SecurityEvents.Read.All** permission is required to read Secure Score control profiles. Verify the permission is consented and re-run the assessment.'
97+
}
98+
elseif ($null -ne $errorMsgQ1) {
99+
$investigateReason = 'Microsoft Graph returned an unexpected error retrieving the EDR in block mode Secure Score control profile. Re-run the assessment in 5–10 minutes and verify **SecurityEvents.Read.All** is consented.'
100+
}
101+
else {
102+
$investigateReason = 'The EDR in block mode Secure Score control or latest Secure Score snapshot could not be located.'
103+
}
104+
105+
$testResultMarkdown = "⚠️ $investigateReason"
106+
$customStatus = 'Investigate'
107+
108+
$params = @{
109+
TestId = '41059'
110+
Title = 'EDR in block mode is enabled when Microsoft Defender Antivirus is not the primary antivirus'
111+
Status = $passed
112+
Result = $testResultMarkdown
113+
CustomStatus = $customStatus
114+
}
115+
Add-ZtTestResultDetail @params
116+
return
117+
}
118+
119+
$profileTitle = $controlProfile.title
120+
121+
# ── Investigate: Q2 failed or returned no snapshot ──
122+
if ($null -ne $errorMsgQ2 -or $null -eq $latestSecureScore) {
123+
if ($null -ne $errorMsgQ2) {
124+
$investigateReason = 'Microsoft Graph returned an unexpected error retrieving the latest Secure Score snapshot. Re-run the assessment in 5–10 minutes.'
125+
}
126+
else {
127+
$investigateReason = 'The EDR in block mode Secure Score control or latest Secure Score snapshot could not be located.'
128+
}
129+
$testResultMarkdown = "⚠️ $investigateReason"
130+
$customStatus = 'Investigate'
131+
132+
$params = @{
133+
TestId = '41059'
134+
Title = 'EDR in block mode is enabled when Microsoft Defender Antivirus is not the primary antivirus'
135+
Status = $passed
136+
Result = $testResultMarkdown
137+
CustomStatus = $customStatus
138+
}
139+
Add-ZtTestResultDetail @params
140+
return
141+
}
142+
143+
# ── Locate the per-control entry inside controlScores[] ──
144+
$controlScoreEntry = $null
145+
if ($latestSecureScore.controlScores) {
146+
$controlScoreEntry = $latestSecureScore.controlScores |
147+
Where-Object { $_.controlName -eq $controlId } |
148+
Select-Object -First 1
149+
}
150+
151+
# ── Investigate: profile exists but snapshot has no scored entry for this control,
152+
# or score/maxScore is null (would produce a false Pass via PowerShell $null coercion) ──
153+
$score = $controlScoreEntry.score
154+
$maxScore = $controlProfile.maxScore
155+
156+
if ($null -eq $controlScoreEntry -or $null -eq $score -or $null -eq $maxScore) {
157+
$testResultMarkdown = '⚠️ The EDR in block mode Secure Score control or latest Secure Score snapshot could not be located.'
158+
$customStatus = 'Investigate'
159+
160+
$params = @{
161+
TestId = '41059'
162+
Title = 'EDR in block mode is enabled when Microsoft Defender Antivirus is not the primary antivirus'
163+
Status = $passed
164+
Result = $testResultMarkdown
165+
CustomStatus = $customStatus
166+
}
167+
Add-ZtTestResultDetail @params
168+
return
169+
}
170+
171+
# ── Determine ignored state from the most recent controlStateUpdates entry ──
172+
$latestStateUpdate = @($controlProfile.controlStateUpdates | Sort-Object { if ($_.updatedDateTime) { [datetime]$_.updatedDateTime } else { [datetime]::MinValue } } -Descending) | Select-Object -First 1
173+
$isIgnored = $latestStateUpdate -and $latestStateUpdate.state -eq 'Ignored'
174+
175+
if (($score -ge $maxScore) -and (-not $isIgnored)) {
176+
$passed = $true
177+
$testResultMarkdown = "✅ EDR in block mode is enabled.`n`n%TestResult%"
178+
}
179+
else {
180+
$passed = $false
181+
$testResultMarkdown = "❌ EDR in block mode is disabled or the Secure Score control is ignored.`n`n%TestResult%"
182+
}
183+
184+
#endregion Assessment Logic
185+
186+
#region Report Generation
187+
188+
$secureScoreUrl = 'https://security.microsoft.com/securescore'
189+
$ignoredDisplay = if ($isIgnored) { '⚠️ Yes' } else { '✅ No' }
190+
$rowStatus = if ($passed) { '✅ Pass' } else { '❌ Fail' }
191+
$lastModified = if ($controlProfile.lastModifiedDateTime) { Get-FormattedDate -DateString $controlProfile.lastModifiedDateTime } else { '' }
192+
193+
$tableRows = "| $(Get-SafeMarkdown $profileTitle) | $controlId | $score | $maxScore | $ignoredDisplay | $lastModified | $rowStatus |`n"
194+
195+
$mdTable = @"
196+
197+
198+
### [Microsoft Secure Score]($secureScoreUrl)
199+
200+
| Control title | Control id | Score | Max score | Ignored | Last modified | Status |
201+
| :------------ | :--------- | :---- | :-------- | :------ | :------------ | :----- |
202+
$tableRows
203+
"@
204+
205+
$testResultMarkdown = $testResultMarkdown -replace '%TestResult%', $mdTable
206+
207+
#endregion Report Generation
208+
209+
$params = @{
210+
TestId = '41059'
211+
Title = 'EDR in block mode is enabled when Microsoft Defender Antivirus is not the primary antivirus'
212+
Status = $passed
213+
Result = $testResultMarkdown
214+
}
215+
if ($customStatus) {
216+
$params.CustomStatus = $customStatus
217+
}
218+
219+
Add-ZtTestResultDetail @params
220+
}

0 commit comments

Comments
 (0)