NAVANEM
Account Management[PowerShell]easy4 min read · jun 13, 2026 · 04:54 utc

Create a Local Admin Account: Idempotent and Locale-Safe

Idempotent PowerShell script creates a local admin using SID S-1-5-32-544 for locale safety. Works on French, German, or any Windows. Pair with LAPS.

by Emanuel De Almeida

TL;DR

  • Idempotent script creates a local administrator account only if it doesn't exist, preventing errors on re-runs
  • Locale-safe by resolving the Administrators group via well-known SID S-1-5-32-544 instead of hardcoded English strings
  • Pair with Windows LAPS for automatic password rotation; never hardcode credentials
  • When we tested on French Windows 11 and German Server 2022, the script resolved the localized group names correctly

Why Does Your Fleet Need a PowerShell Local Administrator Script?

Provisioning a consistent local administrator account is a task every Windows fleet requires. The naive approach breaks instantly on non-English machines or fails with duplicate-member errors on subsequent runs. This PowerShell local administrator script solves both problems through idempotent logic and SID-based group resolution.

Credential security matters enormously here. Stolen credentials were the initial access vector in 22% of confirmed breaches, making it the most common attack method according to Verizon. A well-managed local admin account, paired with LAPS, reduces this attack surface significantly.

What Does This Script Do?

The script checks whether the target account already exists, creates it only when needed, configures the password to never expire, blocks the user from changing it, and adds the account to the local Administrators group. Running it twice on the same machine produces no errors and changes nothing.

This idempotent behavior is critical for RMM deployments. Push it to 500 machines without worrying about which ones already have the account configured. The script handles state detection automatically.

Why Is SID Resolution Important?

Hardcoding "Administrators" as the group name fails on localized Windows installations. French systems use "Administrateurs." German systems use "Administratoren." The well-known SID S-1-5-32-544 identifies the built-in Administrators group regardless of display name, according to Microsoft's security identifier documentation.

This approach eliminates locale-related deployment failures across international environments. Your script works in Tokyo, Berlin, and São Paulo without modification.

Approach

English Windows

French Windows

German Windows

Re-run Safe

Hardcoded "Administrators"

✓ Works

✗ Fails

✗ Fails

✗ Errors

SID S-1-5-32-544 resolution

✓ Works

✓ Works

✓ Works

✓ No-op

What Did We Improve in This Version?

We rewrote the original script with production-grade patterns. Here are the key changes:

  • SID-based group lookup using S-1-5-32-544 instead of literal "Administrators" string
  • Idempotent group membership checks Get-LocalGroupMember before adding to prevent duplicate-member exceptions
  • Splatting syntax replaces fragile backtick line continuations, following PowerShell best practices
  • Proper error handling with $($_.Exception.Message) and -ErrorAction Stop so failures surface immediately
  • SecureString password parameter instead of plaintext, aligning with Microsoft's SecureString guidance
  • Requires directive #Requires -RunAsAdministrator enforces elevation before execution

Removing administrative rights from standard users mitigates 83% of critical Microsoft vulnerabilities on average, according to BeyondTrust. This script helps you maintain that separation by creating dedicated admin accounts.

How Do You Use the Script?

Run from an elevated PowerShell session. The function accepts a SecureString password parameter for security.

powershell
#Requires -RunAsAdministrator

function New-LocalAdminAccount {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory)]
        [string]$Username,
        
        [Parameter(Mandatory)]
        [SecureString]$Password
    )
    
    # Resolve Administrators group by well-known SID (locale-safe)
    $adminGroupSID = [System.Security.Principal.SecurityIdentifier]::new('S-1-5-32-544')
    $adminGroup = $adminGroupSID.Translate([System.Security.Principal.NTAccount]).Value.Split('\')[-1]
    
    try {
        # Check if account exists
        $existingUser = Get-LocalUser -Name $Username -ErrorAction SilentlyContinue
        
        if (-not $existingUser) {
            # Create new local user with splatting
            $userParams = @{
                Name                     = $Username
                Password                 = $Password
                PasswordNeverExpires     = $true
                UserMayNotChangePassword = $true
                Description              = 'Managed local administrator account'
                ErrorAction              = 'Stop'
            }
            New-LocalUser @userParams | Out-Null
            Write-Verbose "Created local user: $Username"
        }
        else {
            Write-Verbose "User $Username already exists, skipping creation"
        }
        
        # Check group membership before adding (idempotent)
        $members = Get-LocalGroupMember -Group $adminGroup -ErrorAction SilentlyContinue
        $isMember = $members | Where-Object { $_.Name -like "*\$Username" }
        
        if (-not $isMember) {
            Add-LocalGroupMember -Group $adminGroup -Member $Username -ErrorAction Stop
            Write-Verbose "Added $Username to $adminGroup group"
        }
        else {
            Write-Verbose "$Username is already a member of $adminGroup"
        }
        
        Write-Output "Local admin account '$Username' configured successfully"
    }
    catch {
        Write-Error "Failed to configure local admin: $($_.Exception.Message)"
        throw
    }
}

Call the function after defining it:

powershell
$securePass = Read-Host -Prompt 'Enter password' -AsSecureString
New-LocalAdminAccount -Username 'LocalAdmin' -Password $securePass -Verbose

How Should You Integrate with Windows LAPS?

Never bake plaintext passwords into scripts or configuration files. Windows LAPS automatically manages and rotates the password of your local administrator account, storing it securely in Microsoft Entra ID or Active Directory. As Microsoft explains, LAPS backs up passwords to domain-joined or Entra-joined devices automatically.

Breaches involving compromised credentials take an average of 292 days to identify and contain, the longest of any attack vector per IBM's Cost of a Data Breach Report. Automated rotation through LAPS drastically shortens this window.

Deploy this script first to create the account structure. Then configure LAPS policies to manage that account. The script runs once to establish the account; LAPS handles ongoing credential hygiene.

What Are the Deployment Best Practices?

Test on a single machine before pushing through your RMM or GPO. Validate the account appears in Local Users and Groups, confirm group membership, and verify you can authenticate.

CISA's Cybersecurity Performance Goals require administrators to maintain separate user and privileged accounts. This script supports that mandate by creating dedicated local admin accounts separate from daily-use credentials.

Consider these deployment patterns:

  1. RMM push with encrypted credential storage in your management platform
  2. GPO startup script paired with LAPS for immediate password takeover
  3. Intune remediation script for Entra-joined devices

If you encounter Intune deployment errors, resolve those before pushing account provisioning scripts.

How Does This Relate to Patch Management?

Local admin accounts become attack vectors when systems remain unpatched. Recent months brought significant security updates, including the June 2026 Patch Tuesday fixes for 206 CVEs and Windows 11 KB5094126. Keep systems current while managing local accounts properly.

Credential theft combined with unpatched vulnerabilities creates compounding risk. Breaches where compromised credentials were the initial vector cost an average of $4.67 million per incident, according to IBM data analyzed by SpyCloud.

FAQ

Why use SID instead of the group name?

The well-known SID S-1-5-32-544 identifies the built-in Administrators group on every Windows installation regardless of language. Hardcoding "Administrators" fails on French, German, Spanish, or any non-English Windows because the display name gets localized. SID resolution guarantees cross-locale compatibility.

How does this script work with Windows LAPS?

This script creates the account structure that LAPS then manages. Run the script once to provision the local admin account with initial settings. Configure LAPS policies afterward to automatically rotate and back up the password. LAPS takes over credential management from that point forward.

What happens if the account already exists?

The script performs a no-op. It checks for existing accounts using Get-LocalUser and verifies group membership with Get-LocalGroupMember before making any changes. Running the script multiple times on the same machine produces no errors and modifies nothing if the account is already configured correctly.

Can I use this with Intune-managed devices?

Yes. Deploy as a remediation script or platform script in Intune. Store the initial password securely using Intune's encrypted variable capabilities. For Entra-joined devices, Windows LAPS integrates directly with Entra ID for password backup and retrieval without requiring on-premises Active Directory.

Why avoid plaintext passwords in scripts?

Plaintext credentials in scripts create persistent exposure. Anyone with read access to the script gains admin credentials. SecureString parameters encrypt the password in memory during execution. Combined with LAPS for ongoing rotation, this approach limits credential exposure to the brief initial provisioning window.

The script

powershell-create-local-admin-account.ps1
#Requires -Version 5.1
#Requires -RunAsAdministrator
<#
.SYNOPSIS
    Creates a local administrator account if it does not already exist.
.DESCRIPTION
    Idempotent: checks for the account first, creates it, sets the password to
    never expire, prevents the user from changing it, and adds it to the local
    Administrators group resolved by its well-known SID (S-1-5-32-544) so it
    works on non-English Windows installs.

    Manage the password with Windows LAPS, do not hard-code it.
.PARAMETER Username
    The account name to create.
.PARAMETER Description
    Description set on the new account.
.PARAMETER Password
    The initial password as a SecureString.
.EXAMPLE
    $pwd = Read-Host -AsSecureString 'Initial password'
    New-LocalAdmin -Username 'svc-admin' -Description 'Break-glass admin' -Password $pwd
.NOTES
    Author : Emanuel De Almeida - https://www.navanem.com
#>
function New-LocalAdmin {
    [CmdletBinding(SupportsShouldProcess)]
    param(
        [Parameter(Mandatory)][string]       $Username,
        [Parameter(Mandatory)][string]       $Description,
        [Parameter(Mandatory)][securestring] $Password
    )

    try {
        if (Get-LocalUser -Name $Username -ErrorAction SilentlyContinue) {
            Write-Host "[skip] '$Username' already exists."
            return
        }

        # Resolve the Administrators group by SID (locale-independent).
        $adminGroup = (Get-LocalGroup -SID 'S-1-5-32-544').Name

        $params = @{
            Name                 = $Username
            Password             = $Password
            FullName             = $Username
            Description          = $Description
            PasswordNeverExpires = $true
            AccountNeverExpires  = $true
            ErrorAction          = 'Stop'
        }
        New-LocalUser @params | Out-Null
        Set-LocalUser -Name $Username -UserMayChangePassword $false -ErrorAction Stop
        Write-Host "[ok]   local user '$Username' created."

        if (-not (Get-LocalGroupMember -Group $adminGroup -Member $Username -ErrorAction SilentlyContinue)) {
            Add-LocalGroupMember -Group $adminGroup -Member $Username -ErrorAction Stop
            Write-Host "[ok]   '$Username' added to '$adminGroup'."
        }
    }
    catch {
        Write-Error "Failed to create '$Username': $($_.Exception.Message)"
    }
}

Review before running. Test in a non-production environment first.

#PowerShell#windows#Security#Hardening#Sysadmin

Related topics