Group Policy Security Audit: How to Find and Fix GPO Misconfigurations That Create Risk

Retool's new app builder is where AI-generated code ships safely
Building apps with AI is easy. Getting them to production safely is another story.
Group Policy is the security configuration layer for most enterprise Windows environments and also one of the most common sources of security misconfigurations. GPO auditing is not part of most security programs -- the assumption is that GPOs set up years ago are correct. In reality, GPOs accumulate over time, conflicting settings create unexpected RSoP (Resultant Set of Policy) results, security settings that were correct in 2015 are incorrect today, and GPO permissions drift. This guide covers the specific GPO misconfigurations most likely to create security risk and how to find them.
Audit GPO Permissions for Write Access
The most dangerous GPO misconfiguration is an overly permissive GPO write permission. If a low-privilege user or group has Edit Settings rights on a GPO linked to domain controllers or privileged OUs, they can modify the GPO to include malicious settings -- startup scripts, registry changes that add them to admin groups, or software installation. Enumerate GPO permissions: Get-GPO -All | ForEach-Object { $gpo = $; $.GetSecurityInfo() | Where-Object { $.Permission -match 'GpoEdit|GpoCreate|GpoApply' -and $.Trustee.SidType -ne 'WellKnownGroup' } | Select-Object @{N='GPO';E={$gpo.DisplayName}}, @{N='Trustee';E={$_.Trustee.Name}}, Permission }. Review any non-administrative group or user account with GpoEdit or GpoCustom permissions on GPOs linked to high-value OUs (Domain Controllers OU, Tier 0 server OUs). Legitimate GPO editors should be limited to Domain Admins or a dedicated GPO management group with a small, documented membership. Remove any unexpected edit permissions immediately.
Check for Conflicting Password Policies
Password policy in Active Directory is set at the domain level via the Default Domain Policy GPO (or a dedicated password policy GPO). A common audit finding: multiple GPOs linked to the domain with Computer Configuration > Windows Settings > Security Settings > Account Policies > Password Policy settings, creating a conflict where the effective policy depends on GPO link order. Only one set of domain-level password policy settings applies (determined by the highest-priority GPO, which is the one with the lowest link order number), but conflicting GPOs make it unclear which policy is active and create a maintenance hazard. Audit: Get-GPO -All | ForEach-Object { $gpo = $; (Get-GPOReport -Guid $.Id -ReportType XML | [xml]).GPO.Computer.ExtensionData | Where-Object { $.name -eq 'Security' } | ForEach-Object { if ($.Extension.Account) { $_ | Select-Object @{N='GPO';E={$gpo.DisplayName}} } } } | Select-Object GPO. Use gpresult /h on a domain controller to see the effective password policy settings and which GPO is applying them. Remove password policy settings from any GPO that is not the authoritative source.
Briefings like this, every morning before 9am.
Threat intel, active CVEs, and campaign alerts, distilled for practitioners. 50,000+ subscribers. No noise.
Audit Startup and Logon Scripts for Insecure Paths
GPO startup scripts (Computer Configuration > Windows Settings > Scripts > Startup) and logon scripts run with elevated privilege on the target machine. If the script path points to a writable network share, any user with write access to that share can replace the script with a malicious version and achieve code execution with SYSTEM or admin rights on every computer the GPO applies to. Enumerate all GPO script paths: Get-GPO -All | ForEach-Object { $report = [xml](Get-GPOReport -Guid $.Id -ReportType XML); $report.GPO.Computer.ExtensionData | Where-Object { $.name -eq 'Scripts' } | Select-Object -ExpandProperty Extension | Select-Object -ExpandProperty Startup | Select-Object @{N='GPO';E={$_.Name}}, Script }. For each script path found: verify the share is readable by target computers but writable only by domain admins. Check the share permissions and NTFS permissions. Scripts stored on SYSVOL are appropriate (SYSVOL is protected by default DFS-R permissions and only writable by Domain Admins). Scripts on non-SYSVOL shares require explicit NTFS permission verification.
Verify Audit Policy Is Actually Applied
A critical but often unchecked GPO audit finding: the Advanced Audit Policy is configured in GPO but not actually applying to target machines because a conflicting 'Audit: Force audit policy subcategory settings to override audit policy category settings' setting is not enabled, or because the GPO is blocked at an OU level. Verify on a DC: auditpol /get /category:* -- this shows the actual applied audit policy, not what GPO intends to apply. Compare with what GPO specifies. Common finding: the 'Audit logon events' category is set to Success and Failure in GPO, but auditpol shows only Success because the GPO is being overridden by a local policy on older DCs. To force Advanced Audit Policy to override legacy settings: the 'Audit: Force audit policy subcategory settings' security option must be enabled (Computer Configuration > Policies > Windows Settings > Security Settings > Local Policies > Security Options). This should be in the Default Domain Controllers Policy.
Check for Orphaned and Unlinked GPOs
Unlinked GPOs (GPOs that exist but are not linked to any OU, domain, or site) are applied to no computers but still represent security risk: they waste administrative attention, can be linked in the future by a low-privilege user who has GPO Link rights on an OU, and may contain outdated settings that would create risk if applied. Find all unlinked GPOs: Get-GPO -All | Where-Object { ($_ | Get-GPOLinks).Count -eq 0 }. For each unlinked GPO: determine if it is needed (ask the GPO owner if documented, or assess content). Delete GPOs with no current purpose. Similarly, find GPOs with empty settings (WMI filter set too restrictively, or all settings removed but GPO not deleted): Get-GPO -All | Where-Object { $.UserVersion -eq 0 -and $.ComputerVersion -eq 0 }. Empty GPOs add processing overhead to policy refresh cycles and are candidates for deletion.
The bottom line
GPO security audits reveal misconfigurations that are invisible to standard security scanning tools -- they require GPO-specific enumeration. The highest-risk findings are GPO edit permissions granted to non-admin users and startup script paths on writable shares. The most common operational finding is conflicting audit policies that silently result in less event logging than intended. Schedule a GPO security review annually at minimum; more frequently after any AD admin staff changes.
Frequently asked questions
Can a standard domain user exploit a misconfigured GPO?
Yes, if the GPO has Edit Settings permissions granted to a group the user is in, or if a startup script path points to a share the user can write to. These are not theoretical -- BloodHound maps GPO write permissions as attack edges, and attackers actively look for them. A user with GPO Edit rights on a GPO linked to the Domain Controllers OU can modify the GPO to add themselves to Domain Admins via a startup script or registry preference, and the change applies the next time Group Policy refreshes (within 90 minutes by default on DCs).
How do I find which GPO is responsible for a specific security setting?
Run gpresult /h c:\report.html on the machine in question and open the HTML report. Navigate to Computer Details > Policy Events or the specific settings section. The report shows which GPO applied each setting. Alternatively, use the Group Policy Management Console: right-click on the OU or domain, select 'Group Policy Results Wizard', and walk through the wizard to generate an RSoP report. For domain-wide settings: query the GPO XML reports for the specific setting using Get-GPOReport.
Is it safe to delete old GPOs?
First unlink the GPO from all OUs and run gpupdate /force on a test machine to confirm no settings are lost (run gpresult before and after to compare). If the effective policy does not change after unlinking, the GPO was either redundant or overridden. Delete the GPO only after confirming the unlink has no impact. Keep a backup of the GPO settings (via GPMC Backup) before deletion in case you need to restore. Never delete GPOs during production changes or on a Friday.
How do I enforce that GPO changes require approval?
There is no built-in GPO change approval workflow in native Windows. Options: use Microsoft Advanced Group Policy Management (AGPM), which is part of Microsoft Desktop Optimization Pack (MDOP), to add a change control workflow to GPO modifications -- changes go through a checked-in/checked-out approval process. Alternatively, use a process control: restrict GPO edit rights to a service account used only via a PAW, require IT change management tickets for GPO modifications, and use GPO backup and version comparison scripts to detect unauthorized changes. Audit Event ID 5136 (directory service object modified) filtered for GPO container changes to detect GPO modifications in your SIEM.
What is GPO tattooing and why does it create security risks?
GPO tattooing occurs when a GPO sets a registry value in a non-managed registry path (not under the Software\Policies hive). When the GPO is removed or the computer leaves the OU where the GPO applies, the tattooed registry values remain -- they are not reversed like managed policy values. Attackers can exploit tattooing intentionally: if they gain temporary GPO edit access, they can write a tattooed registry value (like a Run key or scheduled task via the registry) that persists after the GPO link is removed and the GPO change is rolled back. Tattooing is unavoidable for some registry preference settings. Monitor for unexpected registry values in Run keys and other persistence-relevant locations even after GPO changes are reverted.
How do I audit which GPOs are actually applying to a specific computer or user and identify GPO conflicts?
The primary tool is Group Policy Results (gpresult). Run gpresult /H report.html /F on the target machine to generate a full HTML report showing which GPOs applied, which were filtered or blocked, and which settings won the conflict. For remote analysis, run gpresult /S computername /H report.html as an administrator. The 'Winning GPO' column in the report identifies which GPO's setting took precedence when multiple GPOs configured the same policy. Use the Group Policy Management Console (GPMC) > Group Policy Results wizard for a GUI equivalent that also shows processing order. Key conflict scenarios: a local GPO setting overridden by domain GPO (domain always wins), a site GPO overridden by domain or OU GPO (lower OU wins), a user policy blocked by 'Block Inheritance' on an OU. For troubleshooting slow GPO application, check gpresult for GPO processing times; scripts and folder redirection are the most common culprits for extended processing. Run gpresult /scope computer and gpresult /scope user separately to isolate computer-side from user-side policy application issues.
Sources & references
Free resources
Critical CVE Reference Card 2025–2026
25 actively exploited vulnerabilities with CVSS scores, exploit status, and patch availability. Print it, pin it, share it with your SOC team.
Ransomware Incident Response Playbook
Step-by-step 24-hour IR checklist covering detection, containment, eradication, and recovery. Built for SOC teams, IR leads, and CISOs.
Get threat intel before your inbox does.
50,000+ security professionals read Decryption Digest for early warnings on zero-days, ransomware, and nation-state campaigns. Free, daily, no spam.
Unsubscribe anytime. We never sell your data.

Founder & Cybersecurity Evangelist, Decryption Digest
Cybersecurity professional with expertise in threat intelligence, vulnerability research, and enterprise security. Covers zero-days, ransomware, and nation-state operations for 50,000+ security professionals every morning.
Win a $2,495 Black Hat pass.
Full-access to Black Hat USA 2026 in Las Vegas. Subscribe free to enter.
