PowerShell AD Query: Finding All Users with Password Never Expires Flag in Active Directory


11 views

When working with Active Directory user management, a common task is identifying accounts with non-expiring passwords. While the Search-ADAccount -PasswordNeverExpires command seems straightforward, many administrators report incomplete results due to several technical factors.

For comprehensive results, we need to examine the actual userAccountControl attribute where this setting is stored:

Get-ADUser -Filter {PasswordNeverExpires -eq $true} -Properties PasswordNeverExpires |
Select-Object Name, SamAccountName, DistinguishedName

To scan all domains in your forest, use this enhanced script:

$Domains = (Get-ADForest).Domains
$Results = foreach ($Domain in $Domains) {
    Get-ADUser -Server $Domain -Filter {PasswordNeverExpires -eq $true} -Properties PasswordNeverExpires, PasswordLastSet |
    Select-Object Name, SamAccountName, DistinguishedName, PasswordLastSet, @{
        Name = 'Domain'; Expression = {$Domain}
    }
}
$Results | Export-CSV "NeverExpirePasswords_$(Get-Date -Format yyyyMMdd).csv" -NoTypeInformation

The original Search-ADAccount cmdlet has several constraints:

  • Default 1000 result limit (controlled by -ResultPageSize)
  • Only searches the current domain by default
  • Doesn't expose all relevant attributes for reporting

For more granular control, combine filters:

Get-ADUser -Filter {Enabled -eq $true -and PasswordNeverExpires -eq $true} -Properties * |
Where-Object {$_.PasswordLastSet -lt (Get-Date).AddDays(-365)} |
Select-Object Name, SamAccountName, EmailAddress, Department

For large environments, implement parallel processing:

$Domains = (Get-ADForest).Domains
$UsersWithNeverExpire = $Domains | ForEach-Object -Parallel {
    Import-Module ActiveDirectory
    Get-ADUser -Filter {PasswordNeverExpires -eq $true} -Server $_ -Properties PasswordNeverExpires
} -ThrottleLimit 5

When you identify these accounts, consider:

  • Reviewing service account requirements
  • Documenting business justifications
  • Implementing periodic review workflows
  • Setting alerting for newly configured never-expire flags

The default Search-ADAccount -PasswordNeverExpires cmdlet often returns incomplete results because:

  1. It only searches the current domain by default
  2. Has a default result size limit of 1000 objects
  3. May miss objects in certain organizational units

For a complete forest-wide search, use this enhanced PowerShell script:


# Import Active Directory module
Import-Module ActiveDirectory

# Set unlimited result size
$adSearcher = New-Object DirectoryServices.DirectorySearcher
$adSearcher.PageSize = 50000

# Search all domains in forest
$forest = [System.DirectoryServices.ActiveDirectory.Forest]::GetCurrentForest()
$domains = $forest.Domains

foreach ($domain in $domains) {
    Get-ADUser -Filter {PasswordNeverExpires -eq $true} -Server $domain.Name -Properties PasswordNeverExpires |
    Select-Object Name, SamAccountName, DistinguishedName, Enabled |
    Export-Csv "NeverExpire_$($domain.Name).csv" -NoTypeInformation -Encoding UTF8
}

For enterprises with thousands of users, consider this optimized LDAP query:


$LDAPFilter = "(&(objectCategory=person)(objectClass=user)(userAccountControl:1.2.840.113556.1.4.803:=65536))"
Get-ADUser -LDAPFilter $LDAPFilter -Properties * |
Where-Object {$_.Enabled -eq $true} |
Select-Object Name, SamAccountName, UserPrincipalName

To confirm the accuracy of your results:

  1. Check a sample of returned accounts manually in AD Users and Computers
  2. Compare against known service accounts that typically have this setting
  3. Validate the count against your organization's password policy exceptions

Create a scheduled task with this script to monitor changes:


# Weekly audit script
$DateStamp = Get-Date -Format "yyyyMMdd"
$ReportPath = "C:\ADReports\PasswordAudit_$DateStamp.html"

Search-ADAccount -PasswordNeverExpires | 
ConvertTo-Html -Title "Password Never Expires Report" | 
Out-File $ReportPath

# Email notification
Send-MailMessage -Attachments $ReportPath -Subject "Weekly AD Password Audit" -Body "See attached report"
  • Service accounts should be handled separately from user accounts
  • Review results with your security team before making changes
  • Document all exceptions for compliance purposes