From 707c0ed4b2910d1876929a9d419f74874cb9af30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Przemys=C5=82aw=20K=C5=82ys?= Date: Wed, 18 Feb 2026 11:48:10 +0100 Subject: [PATCH] Address PR feedback: make Defender fallback work without RegistrySettings type --- .../ConvertTo-XMLRegistryDefenderOnReport.ps1 | 18 ++++++++++- Private/Script.GPODictionary.ps1 | 18 ++++++----- Tests/DefenderContent.Tests.ps1 | 30 +++++++++++++++++-- 3 files changed, 55 insertions(+), 11 deletions(-) diff --git a/Private/ConvertTo-XMLRegistryDefenderOnReport.ps1 b/Private/ConvertTo-XMLRegistryDefenderOnReport.ps1 index a698efd..a118d8c 100644 --- a/Private/ConvertTo-XMLRegistryDefenderOnReport.ps1 +++ b/Private/ConvertTo-XMLRegistryDefenderOnReport.ps1 @@ -15,7 +15,23 @@ function ConvertTo-XMLRegistryDefenderOnReport { [PSCustomObject] $GPO ) - foreach ($Registry in $GPO.Settings) { + [Array] $RegistrySettings = @() + if ($GPO.Settings) { + $RegistrySettings = $GPO.Settings + } elseif ($GPO.DataSet) { + # This path supports direct use from dictionary code where RegistrySettings is not requested explicitly. + [Array] $DataSet = $GPO.DataSet + if ($DataSet.Count -gt 0 -and ( + $DataSet[0].PSObject.Properties.Name -contains 'Properties' -or + $DataSet[0].PSObject.Properties.Name -contains 'Registry' -or + $DataSet[0].PSObject.Properties.Name -contains 'Collection' + ) + ) { + $RegistrySettings = Get-XMLNestedRegistry -GPO $GPO -DataSet $GPO.DataSet + } + } + + foreach ($Registry in $RegistrySettings) { if ($Registry.Key -like 'SOFTWARE\Microsoft\Windows Defender*') { [PSCustomObject] [ordered] @{ DisplayName = $GPO.DisplayName diff --git a/Private/Script.GPODictionary.ps1 b/Private/Script.GPODictionary.ps1 index 7b14924..a774ccf 100644 --- a/Private/Script.GPODictionary.ps1 +++ b/Private/Script.GPODictionary.ps1 @@ -1169,10 +1169,9 @@ Category = 'RegistrySettings' Settings = 'Policy' } - ) - ByReports = @( @{ - Report = 'RegistrySettings' + Category = 'RegistrySettings' + Settings = 'RegistrySettings' } ) GPOPath = @( @@ -1180,13 +1179,16 @@ 'Policies -> Administrative Templates -> Windows Components/Microsoft Defender Antivirus' ) Code = { - ConvertTo-XMLGenericPolicy -GPO $GPO -Category 'Windows Components/Windows Defender*', 'Windows Components/Microsoft Defender Antivirus*' + @( + ConvertTo-XMLGenericPolicy -GPO $GPO -Category 'Windows Components/Windows Defender*', 'Windows Components/Microsoft Defender Antivirus*' + ConvertTo-XMLRegistryDefenderOnReport -GPO $GPO + ) | Where-Object { $_ } } CodeSingle = { - ConvertTo-XMLGenericPolicy -GPO $GPO -Category 'Windows Components/Windows Defender*', 'Windows Components/Microsoft Defender Antivirus*' -SingleObject - } - CodeReport = { - ConvertTo-XMLRegistryDefenderOnReport -GPO $GPO + @( + ConvertTo-XMLGenericPolicy -GPO $GPO -Category 'Windows Components/Windows Defender*', 'Windows Components/Microsoft Defender Antivirus*' -SingleObject + ConvertTo-XMLRegistryDefenderOnReport -GPO $GPO + ) | Where-Object { $_ } } } WindowsDefenderExploitGuard = @{ diff --git a/Tests/DefenderContent.Tests.ps1 b/Tests/DefenderContent.Tests.ps1 index 7913045..38c320a 100644 --- a/Tests/DefenderContent.Tests.ps1 +++ b/Tests/DefenderContent.Tests.ps1 @@ -8,8 +8,8 @@ Describe 'Defender content detection' { $Entry = $Script:GPODitionary['WindowsDefender'] $Entry.GPOPath | Should -Contain 'Policies -> Administrative Templates -> Windows Components/Windows Defender' $Entry.GPOPath | Should -Contain 'Policies -> Administrative Templates -> Windows Components/Microsoft Defender Antivirus' - $Entry.ByReports.Report | Should -Contain 'RegistrySettings' - $Entry.CodeReport.ToString() | Should -Match 'ConvertTo-XMLRegistryDefenderOnReport' + ($Entry.Types | Where-Object { $_.Category -eq 'RegistrySettings' -and $_.Settings -eq 'RegistrySettings' }).Count | Should -BeGreaterOrEqual 1 + $Entry.Code.ToString() | Should -Match 'ConvertTo-XMLRegistryDefenderOnReport' } } @@ -61,4 +61,30 @@ Describe 'Defender content detection' { $Result[0].Name | Should -Be 'MpFolderScanThreadCount' } } + + It 'ConvertTo-XMLRegistryDefenderOnReport supports raw DataSet input' { + InModuleScope GPOZaurr { + $GPO = [PSCustomObject] @{ + DisplayName = 'Test Defender GPO' + DomainName = 'contoso.com' + GUID = '11111111-1111-1111-1111-111111111111' + GpoType = 'Computer' + Linked = $true + LinksCount = 1 + Links = @('OU=Workstations,DC=contoso,DC=com') + DataSet = ([xml] @" + + + + + +"@).Root.Registry + } + + [Array] $Result = ConvertTo-XMLRegistryDefenderOnReport -GPO $GPO + $Result.Count | Should -Be 1 + $Result[0].Key | Should -Be 'SOFTWARE\Microsoft\Windows Defender\MpEngine' + $Result[0].Name | Should -Be 'MpFolderScanThreadCount' + } + } }