PowerShell Script to Audit Local Admin Accounts Network-Wide
Local administrator group membership is one of the most common places privilege creep hides in an organization. A contractor gets temporary admin rights for a one-off task and nobody removes them. An IT tech adds themselves to a machine for troubleshooting and forgets to clean up. Over time, the actual list of who has local admin rights across your fleet drifts far from what your security policy says it should be. Manually checking this machine by machine does not scale past a handful of devices, which is exactly why a PowerShell script to audit local admin accounts across your entire network belongs in every IT admin's toolkit.
This tutorial builds a script that queries local administrator group membership across every domain-joined computer, flags accounts that shouldn't be there, and outputs a report you can act on immediately.
Why Local Admin Audits Get Skipped
Auditing local admin membership requires connecting to every machine individually, which used to mean physically checking each device or relying on inconsistent manual spot-checks. Most IT teams know this is important, but without automation it competes for time against more urgent daily fires and gets pushed to "next quarter" indefinitely.
The risk of skipping this is real. Excess local admin rights are one of the most common paths for lateral movement during a security incident, because a compromised account with local admin on multiple machines gives an attacker a much larger blast radius than a standard user account would. Regular audits are also a common requirement in security frameworks like SOC 2 and ISO 27001, so this is not just a best practice — it is often a compliance obligation.
Building the Audit Script
The script needs three components: a way to enumerate target computers, a way to query local admin group membership remotely, and a comparison against your expected baseline to flag anomalies.
Step 1: Get Your List of Target Computers
Pull the list of domain-joined computers from Active Directory using the ActiveDirectory PowerShell module.
1Import-Module ActiveDirectory23$computers = Get-ADComputer -Filter { Enabled -eq $true } -Properties OperatingSystem |4 Where-Object { $_.OperatingSystem -notlike "*Server*" } |5 Select-Object -ExpandProperty Name67Write-Host "Found $($computers.Count) enabled workstations to audit"
Filtering out servers here keeps the scope focused on workstations, since servers typically have a separate, more tightly controlled admin policy and should be audited with different expectations.
Step 2: Query Local Admin Group Membership Remotely
Use Invoke-Command to query each machine's local Administrators group in parallel, which keeps a network-wide audit from taking hours running sequentially.
1$results = Invoke-Command -ComputerName $computers -ScriptBlock {2 try {3 $members = Get-LocalGroupMember -Group "Administrators" -ErrorAction Stop4 [PSCustomObject]@{5 ComputerName = $env:COMPUTERNAME6 Members = ($members.Name -join "; ")7 Status = "Success"8 }9 } catch {10 [PSCustomObject]@{11 ComputerName = $env:COMPUTERNAME12 Members = $null13 Status = "Error: $($_.Exception.Message)"14 }15 }16} -ErrorAction SilentlyContinue1718$results | Export-Csv -Path "local_admin_audit_raw.csv" -NoTypeInformation
Wrapping the query in a try/catch inside the script block matters because some machines will be offline, unreachable, or blocking WinRM, and you want those failures captured in the report rather than silently dropped or crashing the whole audit.
Step 3: Define Your Expected Baseline
Every organization has a small list of accounts that should legitimately appear in local admin groups: the built-in Administrator account, your domain's designated IT admin group, and perhaps an endpoint management service account. Define that baseline explicitly so the script can flag anything outside it.
1$approvedAdmins = @(2 "Administrator",3 "DOMAIN\IT-Admins",4 "DOMAIN\svc-EndpointMgmt"5)67$flagged = foreach ($row in $results) {8 if ($row.Status -eq "Success") {9 $memberList = $row.Members -split "; "10 $unexpected = $memberList | Where-Object { $_ -notin $approvedAdmins }11 if ($unexpected) {12 [PSCustomObject]@{13 ComputerName = $row.ComputerName14 UnexpectedMembers = ($unexpected -join "; ")15 }16 }17 }18}1920$flagged | Export-Csv -Path "local_admin_flagged_accounts.csv" -NoTypeInformation21Write-Host "$($flagged.Count) machines have unexpected local admin accounts"
Step 4: Send a Summary Alert
Wire the results into an email alert so the security or IT team gets notified automatically rather than needing to remember to check the CSV file after each run.
1if ($flagged.Count -gt 0) {2 $body = $flagged | ConvertTo-Html -Property ComputerName, UnexpectedMembers |3 Out-String45 Send-MailMessage -To "security-team@company.com" `6 -From "audit-bot@company.com" `7 -Subject "Local Admin Audit: $($flagged.Count) machines flagged" `8 -Body $body -BodyAsHtml `9 -SmtpServer "smtp.company.com"10}
Real-World Example: Catching Contractor Privilege Creep
An IT team running this audit monthly found that a contractor who had received temporary local admin rights on six machines for a migration project three months earlier had never been removed from any of them, because the removal step depended on someone remembering to do it manually after the project wrapped. The automated flagged-accounts report surfaced all six machines in the first run, and the team added a standing calendar reminder tied to the audit output specifically for time-boxed access grants going forward.
Implementation Guide: Scheduling the Audit
Save the full script and register it as a scheduled task on a management server using Task Scheduler or Register-ScheduledTask, running weekly or monthly depending on how dynamic your environment is.
1$action = New-ScheduledTaskAction -Execute "powershell.exe" `2 -Argument "-File C:\Scripts\Audit-LocalAdmins.ps1"3$trigger = New-ScheduledTaskTrigger -Weekly -DaysOfWeek Monday -At 6am4Register-ScheduledTask -TaskName "WeeklyLocalAdminAudit" `5 -Action $action -Trigger $trigger -RunLevel Highest
Run the scheduled task under a service account with the necessary permissions to query remote machines via WinRM, and make sure that account itself is included in your approved baseline list so it doesn't flag its own audit activity.
Best Practices / Pro Tips
Run this audit on a schedule, not just once. Privilege creep is a continuous problem, and a single audit only gives you a point-in-time snapshot that goes stale within weeks.
Keep your approved baseline list in a separate configuration file rather than hardcoded in the script, so updates to who's authorized don't require editing and re-testing the core audit logic every time.
Handle offline machines gracefully. Laptops that are powered off or disconnected during the audit window will show as errors, not clean results, so track a separate "unable to audit" list and follow up on persistently unreachable machines rather than assuming they're compliant.
Combine this with a broader review of domain-level admin group membership, since local admin rights are only one layer of privilege — Domain Admins, server admin groups, and cloud console access all deserve the same kind of systematic auditing.
Conclusion
Manually checking who has local administrator rights across dozens or hundreds of machines is not realistic, which is exactly why it tends to get skipped until an audit or incident forces the issue. A scheduled PowerShell script that queries local admin membership network-wide, compares it against an approved baseline, and emails a flagged report turns this from a neglected quarterly chore into a routine, low-effort control. Start with a monthly run against your workstation fleet, refine your approved baseline as you learn about legitimate exceptions, and expand to servers once the workstation process is stable.
Frequently Asked Questions
Do I need special permissions to run this script?
Yes. The account running the script needs remote management permissions on target machines, typically through WinRM, and enough Active Directory read access to enumerate the computer list. Running it under a dedicated service account with scoped permissions is more secure than using a personal admin account.
What if some machines are offline during the audit?
Offline or unreachable machines will return an error rather than a clean audit result. Track these separately and follow up, since a machine that consistently fails to respond to the audit deserves investigation on its own.
Can this script check servers as well as workstations?
Yes, but consider auditing them separately with a different approved baseline, since servers often have legitimately different and more numerous admin accounts than standard workstations.
How often should this audit run?
Monthly is a reasonable starting cadence for most organizations, though environments with frequent contractor access or high turnover may benefit from a weekly schedule instead.
Related articles: PowerShell Script to Automate Employee Offboarding and Access Revocation, PowerShell Azure Automation: Manage Cloud Resources Fast, PowerShell File Organization Script: Auto-Sort Downloads in Seconds
Sponsored Content
Interested in advertising? Reach automation professionals through our platform.
