Thursday, April 17, 2025

🧼 Cleanup: Invalid SID Members in Local Groups (Windows Server Maintenance)

🧼 Cleanup: Invalid SID Members in Local Groups (Windows Server Maintenance)

Overview

This PowerShell script scans all local groups for orphaned (invalid) SIDs — entries left behind after a user or service account has been deleted. These show as raw SIDs (e.g., S-1-5-21-...) in group membership.

We use NinjaOne to deploy this as a recurring cleanup task across servers.

🔧 What It Does

  • Enumerates all local groups
  • Identifies broken/unresolvable SID entries
  • Removes only invalid entries
  • Outputs all actions to NinjaOne

🛠 PowerShell Script

PowerShell Script

$badEntries = @()

$localGroups = Get-LocalGroup | Select-Object -ExpandProperty Name

foreach ($groupName in $localGroups) {
    Write-Output "`nProcessing group: $groupName"
    $badSIDs = @()

    $output = powershell -Command "Get-LocalGroupMember -Group '$groupName'" 2>&1

    foreach ($line in $output) {
        if ($line -match "SID '([^']+)'") {
            $badSIDs += $matches[1]
        }
    }

    if ($badSIDs.Count -gt 0) {
        $group = [ADSI]"WinNT://./$groupName,group"
        foreach ($sid in $badSIDs | Select-Object -Unique) {
            $path = "WinNT://$sid"
            try {
                $group.Remove($path)
                Write-Output "Removed: $sid from $groupName"
                $badEntries += [PSCustomObject]@{ Group = $groupName; SID = $sid; Status = "Removed" }
            } catch {
                Write-Warning "Failed to remove: $sid from $groupName"
                $badEntries += [PSCustomObject]@{ Group = $groupName; SID = $sid; Status = "Failed" }
            }
        }
    } else {
        Write-Output "No orphaned SIDs found in $groupName"
    }
}

$badEntries | Format-Table
        

🧪 Example Output

Processing group: Administrators
Removed: S-1-5-21-...-6274 from Administrators

Processing group: Users
Removed: S-1-5-21-...-6835 from Users
Removed: S-1-5-21-...-13465 from Users
    

🔒 Safety

  • Only removes entries matching S-1-5-21-*
  • Only removes if the SID causes an error in Get-LocalGroupMember
  • Leaves all valid users/groups untouched