A questão é que o loop for acha que o colchete final está dentro do comando powershell.
A solução possível é criar uma função e chamá-la do loop:
for /l %%x in (1, 1, %k%) do (
call :getPassword password
)
:getPassword
set "psCommand=powershell -Command "$pword = read-host 'Enter Password' -AsSecureString ; ^
$BSTR=[System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($pword); ^
[System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR)""
for /f "usebackq delims=" %%p in ('%psCommand%') do set password=%%p
EXIT /B 0