Skip to main content

How to Set Password Complexity Policy in Batch Script

Password complexity requirements ensure that users don't choose simple, easily guessable passwords like "password123." When enabled, Windows requires that every new password contains characters from at least three of the following categories: uppercase letters, lowercase letters, numbers, and symbols. While this is easily toggled in the secpol.msc GUI, automating this across multiple machines requires using the secedit utility to import a security template.

This guide explains how to enforce password complexity using a Batch script.

Why Enforce Password Complexity?

  • Brute Force Protection: Making it significantly harder for automated tools to guess credentials by increasing the "Entropy" of the chosen passwords.
  • Compliance Standards: Meeting the requirements for modern security frameworks (like PCI-DSS or HIPAA), which mandate complex authentication.
  • System Hardening: Preventing users from using common dictionary words that are the first target of hackers.
No 'Net Accounts' Support

Unlike password length, complexity cannot be enabled using the net accounts command. It must be applied via a .inf security template using the secedit tool.

Method: Using Secedit with a Temporary Template

To enable complexity, we create a small configuration file and "Configure" the local security database with it.

@echo off
setlocal

:: Check for admin rights
net session >nul 2>&1
if %errorlevel% neq 0 (
echo [ERROR] Administrator privileges are required.
pause
exit /b 1
)

set "TMP_INF=%TEMP%\complexity_policy_%RANDOM%.inf"
set "TEMP_DB=%TEMP%\complexity_%RANDOM%.sdb"

echo [PROCESS] Creating password complexity template...

:: Create a properly encoded Unicode INF file
powershell -NoProfile -Command ^
"[System.IO.File]::WriteAllText('%TMP_INF%', '[Unicode]`r`nUnicode=yes`r`n[System Access]`r`nPasswordComplexity = 1`r`n', [System.Text.Encoding]::Unicode)"

echo [PROCESS] Applying policy to local security database...
secedit /configure /db "%TEMP_DB%" /cfg "%TMP_INF%" /areas SECURITYPOLICY >nul

if %errorlevel% equ 0 (
echo [SUCCESS] Password complexity is now ENFORCED.
echo [NOTE] This applies the next time a password is changed.
) else (
echo [ERROR] Failed to apply policy. Code: %errorlevel%
echo [HELP] Check: %windir%\security\logs\scesrv.log
)

:: Cleanup
del "%TMP_INF%" >nul 2>&1
del "%TEMP_DB%" >nul 2>&1
del "%TEMP_DB%.log" >nul 2>&1
del "%TEMP_DB%.jfm" >nul 2>&1
pause

Verifying the Complexity Status

To confirm the setting was applied correctly, you can export the current policy and check the value.

@echo off
setlocal

:: Check for admin rights
net session >nul 2>&1
if %errorlevel% neq 0 (
echo [ERROR] Administrator privileges are required.
pause
exit /b 1
)

set "CHECK_INF=%TEMP%\check_policy_%RANDOM%.inf"

echo [PROCESS] Verifying current complexity status...

secedit /export /cfg "%CHECK_INF%" /areas SECURITYPOLICY >nul 2>&1

if %errorlevel% neq 0 (
echo [ERROR] Could not export security policy.
pause
exit /b 1
)

for /f "tokens=1,2 delims==" %%a in ('findstr /i "PasswordComplexity" "%CHECK_INF%" 2^>nul') do (
set "VALUE=%%b"
)

if "%VALUE%"==" 1" (
echo [STATUS] Password Complexity: ENABLED
) else if "%VALUE%"==" 0" (
echo [STATUS] Password Complexity: DISABLED
) else (
echo [STATUS] Password Complexity: Could not determine
)

del "%CHECK_INF%" >nul 2>&1
pause

Creating a Robust Security Enforcer

A professional script backs up current settings, then sets both the minimum length and the complexity in one operation for maximum system hardening.

@echo off
setlocal

echo ============================================================
echo Global Password Security Enforcer
echo ============================================================

:: 1. Verify Administrative Rights
net session >nul 2>&1
if %errorlevel% neq 0 (
echo [CRITICAL] Admin rights REQUIRED for security database edits.
pause
exit /b 1
)

:: 2. Backup current settings
set "BACKUP_FILE=%~dp0PasswordPolicy_Backup_%date:~-4%%date:~-10,2%%date:~-7,2%.inf"
echo [STEP 1/3] Backing up current password policy...
secedit /export /cfg "%BACKUP_FILE%" /areas SECURITYPOLICY >nul

if %errorlevel% neq 0 (
echo [ERROR] Backup failed. Aborting for safety.
pause
exit /b 1
)
echo [PASS] Backup saved: %BACKUP_FILE%

:: 3. Set Length (Fast method)
echo.
echo [STEP 2/3] Setting Minimum Length to 10...
net accounts /minpwlen:10 >nul
if %errorlevel% equ 0 (
echo [PASS] Minimum length set to 10.
) else (
echo [WARN] Could not set minimum length.
)

:: 4. Set Complexity (Secedit method with proper encoding)
echo.
echo [STEP 3/3] Enabling Complexity Requirements...
set "TMP_INF=%TEMP%\sec_fix_%RANDOM%.inf"
set "TEMP_DB=%TEMP%\sec_fix_%RANDOM%.sdb"

powershell -NoProfile -Command ^
"[System.IO.File]::WriteAllText('%TMP_INF%', '[Unicode]`r`nUnicode=yes`r`n[System Access]`r`nPasswordComplexity = 1`r`n', [System.Text.Encoding]::Unicode)"

secedit /configure /db "%TEMP_DB%" /cfg "%TMP_INF%" /areas SECURITYPOLICY >nul

if %errorlevel% equ 0 (
echo [PASS] Password complexity enabled.
) else (
echo [FAIL] Complexity policy failed. Check: %windir%\security\logs\scesrv.log
)

:: Cleanup
del "%TMP_INF%" >nul 2>&1
del "%TEMP_DB%" >nul 2>&1
del "%TEMP_DB%.log" >nul 2>&1
del "%TEMP_DB%.jfm" >nul 2>&1

echo.
echo [DONE] Security profile updated.
echo ============================================================
pause

Common Pitfalls and How to Avoid Them

Administrative Rights

The secedit tool modifies the core Windows security database. You must run your Batch script (and the CMD window) as an Administrator.

INF Encoding

secedit is sensitive to file encoding. It typically expects UTF-16 LE (Unicode) files.

Wrong Way:

echo [System Access] > config.inf
:: This creates an ANSI file, which secedit may reject or interpret incorrectly.

Correct Way: Use PowerShell to generate properly encoded .inf files (as shown in the scripts above), or use a template that was originally exported by secedit /export.

SEO and UX Tip

Advise your users that a value of 1 means Enabled, and 0 means Disabled.

Best Practices for Password Management

  1. Educate Users: Complex passwords are harder to remember. Advise users to use "Passphrases" (e.g., BlueCats!234) which are complex but easier to recall.
  2. Combine with Lockout Threshold: Complexity alone isn't enough; pair it with an account lockout policy (net accounts /lockoutthreshold:5) to stop automated guessing.
  3. Audit Regularly: Periodically run your verification script to ensure that a local change hasn't disabled the requirement.
Domain GPO

On a domain-joined machine, the Domain Group Policy (GPO) will overwrite your local settings. If the script succeeds but the policy doesn't seem to "Stick," check your GPO settings in the Active Directory environment.

Conclusion

Enforcing password complexity via Batch script is a critical competency for any security-conscious Windows administrator. By moving beyond simple length requirements and leveraging the secedit tool to mandate complex authentication, you create a significantly more resilient defense against unauthorized access. This professional approach to system hardening reduces the impact of credential-harvesting attacks and ensures that your entire fleet of workstations adheres to the highest modern security standards across the Windows ecosystem.