LAPS rotates the local Administrator password on schedule, and if you've read the sibling post on this blog you already know how to prove that rotation is actually happening rather than just configured. But a rotating password answers only half the question. It tells you the built-in account's credential is fresh. It tells you nothing about who else is sitting in that same Administrators group — the contractor who needed "just temporary" elevation eight months ago to install one piece of software, and whose account nobody ever removed. This post is about finding that second, quieter problem: not whether the password rotates, but whether the membership list itself has drifted away from what it should be.
Get-LocalAdminGroupDrift.ps1 is free and open source. Download it from the Imran76Awan/Daily-Tasks repository on GitHub — no sign-in required. Note: at the time of publishing this script has not yet been pushed to GitHub — the path below is where it will live once it has been tested and confirmed working.
The Problem — the contractor who left in January is still an admin in July
Here's the scenario, and if you've been doing endpoint engineering for more than a year, some version of it has already happened in your estate. A contractor was brought in for a six-week project. Their laptop needed a vendor-supplied driver installer that demanded local admin rights to run. Rather than build a proper Win32 app package with the right install context, someone — reasonably, under deadline pressure — added the contractor's personal Entra account to the local Administrators group on their assigned device "just for the install." The project ended. The contractor's badge was returned. Their Entra account may even have been disabled eventually. But nobody ever touched that local Administrators group membership, because nothing prompted anyone to look.
Six months later, that laptop gets reassigned to a new starter. The new starter now has local admin rights on their machine through an account that shouldn't be there at all, inherited silently from a decision nobody remembers making. Multiply this by every "can you just make me admin temporarily" Slack message your helpdesk has fielded over the last two years, across every device those requests touched, and you have a real, unquantified attack surface that nothing in your standard Intune compliance dashboard will ever surface.
Notice the second finding in that output — a whole department distribution/security group with local admin rights. That one is worse than the individual contractor account, because it means every member of Marketing, present and future, silently inherits local admin on this device the moment they're added to that group in Entra ID or Active Directory. Nobody who added that group meant for that to happen at this scale. Drift compounds.
Get-MgDeviceManagementManagedDevice or any other Graph call. That's not a gap in this post's research — it's a real architectural fact about how Windows stores this data. Everything from here on is built around that constraint, not around it.Why It Happens — nothing native ever asks the question
The root cause isn't carelessness, exactly — it's the absence of a natural trigger. Elevation requests get granted through whatever channel is fastest: a helpdesk ticket resolved with net localgroup Administrators CONTOSO\username /add, a quick GPO Restricted Groups edit, or a one-off addition through Computer Management on the device itself. Granting access is a single action with an immediate, visible payoff — the user can now install their software. Reverting access has no equivalent trigger. Nobody's calendar reminds them "check whether Jane still needs local admin on WKS-042." The request that started the grant has an end; the grant itself does not, unless someone deliberately closes the loop.
Compounding that, most organisations' offboarding checklists focus on the things that are centrally visible and therefore feel urgent: disable the Entra ID account, revoke licenses, remove from distribution groups, wipe the Autopilot-enrolled device if it's being returned. Local Administrators group membership on a device that isn't being wiped — because it's being reassigned to someone else, not retired — simply isn't on that checklist, because nobody built tooling that would surface it as a checklist item in the first place.
And unlike almost every other identity or access control surface covered on this blog, that absence of tooling isn't a documentation gap you can fix by reading further. It's structural.
Administrator account (SID ending in -500), even if it's disabled. If you deploy the detection script below without putting that account (and your LAPS-managed account, if it uses a different name) on your -ExpectedMembers baseline, every single device in your fleet will report a false-positive "unexpected member" on its very first run. Build your baseline list before you deploy at scale, not after the alert flood starts.How to Verify — run it by hand on one device first
Before you deploy anything to a fleet, confirm the check itself makes sense against a real device you understand. Open an elevated PowerShell session — this needs administrative rights on the local device, same as any command that touches the SAM database — and run the one cmdlet this entire post is built around:
Get-LocalGroupMember is a standard cmdlet in the Microsoft.PowerShell.LocalAccounts module, built into Windows PowerShell 5.1 and PowerShell 7 on every Windows 10/11 device — no module install required, no elevated tenant permissions required, because this is a purely local query against the device's own SAM database. Run it now on a device you already understand, write down the names it returns, and decide which ones genuinely belong there. That list becomes your baseline. If you skip this step and jump straight to deploying the script at scale with a guessed baseline, you'll spend your first week drowning in false positives instead of real findings.
One thing worth checking at the same time: whether either of the two legacy enforcement mechanisms is already configured on this device, because the detection script below is valuable regardless of the answer, but it's worth knowing which situation you're in.
The Fix — a detection script deployed as an Intune Proactive Remediation
The fix here isn't a policy setting, because — as the blue callout above explained — there is no Graph endpoint and no simple centralized query that answers "who is in the local Administrators group across my fleet." What does exist, and what this blog has already used twice for exactly this class of problem, is a device-side detection script deployed through Intune Proactive Remediations. Two sibling posts on this blog already establish this exact pattern for surfacing device-local state that Graph can't see directly: the WHfB health scripts post, which checks PRT and NGC key state, and the Primary Refresh Token remediation post. Both use the same mechanism this post relies on: a script runs locally on the device, exits with a code Intune understands, and Intune's own reporting surfaces the aggregate result centrally — while the script's own console output, captured per-device, is what actually shows you the detail.
Get-LocalAdminGroupDrift.ps1 runs Get-LocalGroupMember -Group "Administrators", compares the result against an -ExpectedMembers baseline you supply, and reports two categories of drift: accounts present that shouldn't be (unexpected), and accounts on the baseline that are missing entirely (which matters most when the missing account is your LAPS-managed one — see the green tip below). It exits 1 if either condition is found, 0 if the device matches baseline exactly.
Deploy the detection script as its own Proactive Remediation policy — detection only, no remediation script attached, which is a fully supported configuration in Intune. Here's the exact path:
- Name: Local Administrators Group Drift Audit
- Detection script: Upload
Get-LocalAdminGroupDrift.ps1— edit the$ExpectedMembersdefault array in the script itself to match your real baseline before uploading - Remediation script: none — leave this policy detection-only, per the red warning above
- Run this script using the logged-on credentials: No (run as SYSTEM — reading the Administrators group doesn't require user context, and SYSTEM has consistent access on every device)
- Run script in 64-bit PowerShell: Yes
- Schedule: Daily — membership doesn't change hourly, and this keeps the script's footprint negligible
- Scope: Assign to All Devices (or your Windows device group) — this is exactly the kind of check that's most valuable run everywhere, not just on devices you already suspect
Two enforcement paths exist for declaring expected local group membership as policy, and it's worth documenting both, because the detection script above catches drift regardless of whether either is in place — that's exactly why it's still worth deploying even if you already use one of them.
If you'd rather query drift findings across many devices at once in KQL instead of clicking through per-device output in the Intune portal, the natural extension is writing Get-LocalGroupMember results to a custom Log Analytics table via the Azure Monitor Agent's custom log ingestion, then querying it centrally. That's a genuine enhancement worth building once you've validated the baseline approach — but it's an addition on top of this script, not a replacement for the detection-script pattern itself.
Proof It Worked — watching the compliance number fall, then checking one device's own output
After deploying the policy and letting it run against your fleet for the first cycle, the Proactive Remediations report gives you the aggregate view first. This is the "how many devices failed this check" number — not a live per-device membership list, but a genuinely useful signal of scale:
142 out of 1,842 devices with unexpected local admin members is not a small number — roughly 7.7% of the fleet carrying access nobody currently accounts for. That number on its own tells you scale. It doesn't tell you what to do about any individual device. For that, drill into a specific device's detection run and read the captured console output, which is the actual per-device detail this whole approach exists to surface:
Clicking into this device's row shows the full script output captured at detection time — the same log lines from the ps-block above, including the two flagged accounts, right there in the portal. No Graph query, no export — this per-device console capture is Intune's built-in mechanism for exactly this kind of finding.
After investigating and manually removing the contractor account (confirmed genuinely stale — the account itself had been disabled in Entra ID since January) and correcting the accidental group nesting for Marketing-AllStaff, the next day's detection run on that same device shows compliant, and the fleet-wide number drops accordingly over the following week as the backlog gets worked through — not all 142 at once, since each finding still needs the same investigate-before-remove judgment call the red warning above insists on.
| Metric | Before cleanup | One week after |
|---|---|---|
| Devices with issues found | 142 | 31 |
| Devices confirmed compliant | 1,700 | 1,811 |
| Findings confirmed as legitimate (left in place) | — | 19 |
| Findings removed after investigation | — | 92 |
That last row matters as much as the compliance number. Not every UNEXPECTED finding is wrong — some turn out to be legitimate service accounts or support groups that were simply never documented as "expected," and the right fix there is updating your baseline, not touching the device. The script's job is to surface the question. Answering it is still a human judgment call, every time.
I'll deploy and tune a Proactive Remediation like this one for your environment, help you build an accurate expected-members baseline, and work through the investigation backlog with your team.
References
- Remediations (Proactive Remediations) in Microsoft Intune — Microsoft Learn
- Get-LocalGroupMember cmdlet reference — Microsoft Learn
- Windows LAPS overview — Microsoft Learn
- Use PowerShell scripts on Windows devices in Intune — Microsoft Learn
Get-LocalAdminGroupDrift.ps1 is a read-detection script — it never modifies the group it audits. Safe to deploy fleet-wide as a detection-only policy while you build up an accurate expected-members baseline for your environment.