The answers that say, "You have to do it from a script" are pretty much right. There is not currently (as of 2025) a native way to do it through Group Policy. Here are two scripts that may help:
Get-WMINameSpaceSecurity:
<# .Synopsis A Script for getting the current security descriptor of a WMI namespace. .DESCRIPTION A Script for getting the current security descriptor of a WMI namespace. .EXAMPLE Get-WMINamespaceSecurity.ps1 -NameSpace "root\cimv2" .EXAMPLE Get-WmiNamespaceSecurity.ps1 "root\cimv2" -ComputerName <remote computer> .NOTES Blog links: https://blogs.msdn.microsoft.com/wmi/2009/07/20/scripting-wmi-namespace-security-part-1-of-3/ https://blogs.msdn.microsoft.com/wmi/2009/07/23/scripting-wmi-namespace-security-part-2-of-3/ https://blogs.msdn.microsoft.com/wmi/2009/07/27/scripting-wmi-namespace-security-part-3-of-3/ Original Content by Jason Eberhardt #> Param ([Parameter (Mandatory=$true,Position=0)] [string]$Namespace, [Parameter(Mandatory=$false)] [string]$ComputerName=".", [Parameter(Mandatory=$false)] [System.Management.Automation.PSCredential]$Credential=$null) Begin { #https://learn.microsoft.com/en-us/windows/win32/api/wbemcli/ne-wbemcli-wbem_security_flags #Spaces around the "=" sign are required for syntax [Flags()] enum WBEMSecurity { Enable = 0x01 MethodExecute = 0x02 FullWrite = 0x04 PartialWrite = 0x08 ProviderWrite = 0x10 RemoteAccess = 0x20 Subscribe = 0x40 Publish = 0x80 ReadSecurity = 0x20000 WriteSecurity = 0x40000 } #https://learn.microsoft.com/en-us/previous-versions/windows/desktop/secrcw32prov/win32-ace [Flags()] enum WBEMInheritance { OBJECT_INHERIT = 0x01 CONTAINER_INHERIT = 0x02 NO_PROPAGATE_INHERIT = 0x04 INHERIT_ONLY = 0x08 INHERITED = 0x10 SUCCESSFUL_ACCESS_FLAG = 0x40 FAILED_ACCESS_FLAG = 0x80 } } Process { if ($PSBoundParameters.ContainsKey("Credential")) { $Output=Invoke-WmiMethod -Namespace $Namespace -Path "__systemsecurity=@" -ComputerName $ComputerName -Name "GetSecurityDescriptor" } else { $Output=Invoke-WmiMethod -Namespace $Namespace -Path "__systemsecurity=@" -ComputerName $ComputerName -Credential $Credential -Name "GetSecurityDescriptor" } if ($Output.ReturnValue -ne 0) {throw "GetSecurityDescriptor failed: $($Output.ReturnValue)" } $ACL=$Output.Descriptor.DACL $Results=@() for ($i=0; $i -lt $ACL.Count; $i++) { $Results+=[PSCustomObject]@{Trustee=$ACL[$i].Trustee.Domain+"\"+$ACL[$i].Trustee.Name;AccessType=[System.Security.AccessControl.AccessControlType]$ACL[$i].AceType;AccessFlags=[WBEMInheritance]$ACL[$i].AceFlags;AccessMask=[WBEMSecurity]$ACL[$i].AccessMask} } $Results }
Set-WMINameSpaceSecurity:
<# .Synopsis A Script for modifying the current security descriptor of a WMI namespace. .DESCRIPTION A Script for modifying the current security descriptor of a WMI namespace. .EXAMPLE Set-WMINamespaceSecurity.ps1 -namespace root/cimv2 -Account "contoso\AD - Remote WMI Access" -operation Add -permissions Enable .EXAMPLE Set-WmiNamespaceSecurity.ps1 root/cimv2 add steve Enable,RemoteAccess .NOTES Blog links: https://blogs.msdn.microsoft.com/wmi/2009/07/20/scripting-wmi-namespace-security-part-1-of-3/ https://blogs.msdn.microsoft.com/wmi/2009/07/23/scripting-wmi-namespace-security-part-2-of-3/ https://blogs.msdn.microsoft.com/wmi/2009/07/27/scripting-wmi-namespace-security-part-3-of-3/ Original Content by Steve Lee Modified by Graeme Bray Modified a lot by Jason Eberhardt #> Param ([Parameter (Mandatory=$true,ParameterSetName="ADD")] [Parameter (Mandatory=$true,ParameterSetName="DEL")] [string]$Namespace, [Parameter (Mandatory=$true,ParameterSetName="ADD")] [switch]$Add, [Parameter (Mandatory=$true,ParameterSetName="DEL")] [switch]$Delete, [Parameter (Mandatory=$true,ParameterSetName="ADD")] [Parameter (Mandatory=$true,ParameterSetName="DEL")] [string]$Account, [Parameter (Mandatory=$true,ParameterSetName="ADD")] [ValidateSet("PartialWrite","Enable","ProviderWrite","ReadSecurity","WritesSecurity","MethodExecute","RemoteAccess","FullWrite")] [string[]]$Permissions, [Parameter (Mandatory=$false,ParameterSetName="ADD")] [switch]$AllowInherit, [Parameter (Mandatory=$false,ParameterSetName="ADD")] [switch]$Deny, [Parameter (Mandatory=$false,ParameterSetName="ADD")] [Parameter (Mandatory=$false,ParameterSetName="DEL")] [string]$ComputerName=".", [Parameter (Mandatory=$false,ParameterSetName="ADD")] [Parameter (Mandatory=$false,ParameterSetName="DEL")] [System.Management.Automation.PSCredential]$Credential=$null) Begin { $ACCESS_ALLOWED_ACE_TYPE=0x0 $ACCESS_DENIED_ACE_TYPE=0x1 $OBJECT_INHERIT_ACE_FLAG=0x1 $CONTAINER_INHERIT_ACE_FLAG=0x2 } Process { Function Get-AccessMaskFromPermission($Permissions) { $WBEM_ENABLE = 0x01 $WBEM_METHOD_EXECUTE = 0x02 $WBEM_FULL_WRITE_REP = 0x04 $WBEM_PARTIAL_WRITE_REP = 0x08 $WBEM_WRITE_PROVIDER = 0x10 $WBEM_REMOTE_ACCESS = 0x20 $WBEM_RIGHT_SUBSCRIBE = 0x40 $WBEM_RIGHT_PUBLISH = 0x80 $READ_CONTROL = 0x20000 $WRITE_DAC = 0x40000 $WBEM_RIGHTS_FLAGS=$WBEM_ENABLE,$WBEM_METHOD_EXECUTE,$WBEM_FULL_WRITE_REP,$WBEM_PARTIAL_WRITE_REP,$WBEM_WRITE_PROVIDER,$WBEM_REMOTE_ACCESS,$READ_CONTROL,$WRITE_DAC $WBEM_RIGHTS_STRINGS="Enable","MethodExecute","FullWrite","PartialWrite","ProviderWrite","RemoteAccess","ReadSecurity","WriteSecurity" $PermissionTable=@{} for ($i=0; $i -lt $WBEM_RIGHTS_FLAGS.Length; $i++) { $PermissionTable.Add($WBEM_RIGHTS_STRINGS[$i].ToLower(), $WBEM_RIGHTS_FLAGS[$i]) } $AccessMask=0 foreach ($Permission in $Permissions) { if (-not $PermissionTable.ContainsKey($Permission.ToLower())) { throw "Unknown permission: $Permission`nValid permissions: $($PermissionTable.Keys)" } $AccessMask+=$PermissionTable[$Permission.ToLower()] } $AccessMask } #Get-AccessMaskFromPermission if ($PSBoundParameters.ContainsKey("Credential")) { $RemoteParams=@{ComputerName=$ComputerName;Credential=$Credential} } else {$RemoteParams=@{ComputerName=$ComputerName}} $InvokeParams=@{Namespace=$Namespace;Path="__systemsecurity=@"}+$RemoteParams $Output=Invoke-WmiMethod @InvokeParams -Name "GetSecurityDescriptor" if ($Output.ReturnValue -ne 0) {throw "GetSecurityDescriptor failed: $($Output.ReturnValue)" } $ACL=$Output.Descriptor if ($ComputerName -eq ".") { $ComputerName=$env:COMPUTERNAME } # Local or NT-style accounts if ($Account.Contains('\')) { $DomainAccount=$Account.Split('\') $Domain=$DomainAccount[0] if (($Domain -eq ".") -or ($Domain -eq "BUILTIN")) { $Domain=$ComputerName } $AccountName=$DomainAccount[1] } # Modern style accounts elseif ($Account.Contains('@')) { $DomainAccount=$Account.Split('@') $Domain=(Get-ADDomain -Server $DomainAccount[1]).NetBIOSName $AccountName=$DomainAccount[0] } # Local accounts only else { $Domain=$ComputerName $AccountName=$Account } $SetParams=@{Class="Win32_Account";Filter="Domain='$Domain' and Name='$AccountName'"}+$RemoteParams $Win32Account=Get-WmiObject @SetParams if ($Win32Account -eq $null) { throw "Account was not found: $Account" } if ($Add.IsPresent) { if ($Permissions -eq $null) { throw "-Permissions must be specified for an add operation" } $AccessMask=Get-AccessMaskFromPermission($Permissions) $ACE=(New-Object System.Management.ManagementClass("win32_Ace")).CreateInstance() $ACE.AccessMask=$AccessMask if ($AllowInherit.IsPresent) { $ACE.AceFlags=$CONTAINER_INHERIT_ACE_FLAG } else { $ACE.AceFlags=0 } $Trustee=(New-Object System.Management.ManagementClass("win32_Trustee")).CreateInstance() $Trustee.SidString=$Win32Account.Sid $ACE.Trustee=$Trustee if ($Deny.IsPresent) { $ACE.AceType=$ACCESS_DENIED_ACE_TYPE } else { $ACE.AceType=$ACCESS_ALLOWED_ACE_TYPE } $ACL.DACL += $ace.psobject.immediateBaseObject } else { if ($Permissions -ne $null) { throw "Permissions cannot be specified for a delete operation" } [System.Management.ManagementBaseObject[]]$newDACL=@() foreach ($ACE in $ACL.DACL) { if ($ACE.Trustee.SIDString -ne $Win32Account.SID) { $NewDACL+=$ACE.PSObject.ImmediateBaseObject } } $ACL.DACL=$NewDACL.PSObject.ImmediateBaseObject } $SetParams=@{Name="SetSecurityDescriptor";ArgumentList=$ACL.PSObject.ImmediateBaseObject}+$InvokeParams $Output=Invoke-WmiMethod @SetParams if ($output.ReturnValue -ne 0) { throw "SetSecurityDescriptor failed: $($Output.ReturnValue)" } }