Search code examples
powershellescapingspecial-characterspowershell-5.0

Escaping all password special characters in Powershell for Variable


I have the following scenario, running on Powershell v5:

A Powershell script pulls several bits of information from an API call to a 3rd party system in a bulk for-each loop and assigns them to Variables. Amongst the information that is pulled is Passwords (this is being done to get rid of said 3rd party system and to migrate it to something that doesn't allow you to retrieve passwords in plain text):

$userset = Invoke-WebRequest -Method Post -Uri "https://$Url/path/to/api.asmx" -Headers $Headers -Body $usercall

$xmluserset = [xml] $userset.Content

$userset2 = $xmluserset.Envelope.Body.UserSettingsResult.settingValues.string

$userpasstemp = $userset2[1].trimstart("password")
$userpass = $userpasstemp.trimstart("=")

These passwords are then used elsewhere in the Script.

For example, they are passed to a different API and need to be in a URL compatible format and so I run this:

$urlescapeduserpass = [uri]::EscapeDataString($userpass)

which works for that section of the Script

The problem is that these passwords can contain any of the special characters: !"#$%&'()*+,-./:;<=>?@[]^_`{|}~

And when I call another part of the script, the special characters in the password string cause a failure and the script to exit. This occurs when using either the call command:

& .\application.exe --option1 $option1 --user1 $user --password1 $userpass

or when using invoke-expression

$command = "$path\application.exe  --option1 $option1 --user1 $user --password1  $userpass"
Invoke-Expression $command

I've tried using Regex, using the -replace cmdlet:

$escapedpass = $userpass -replace ' !"#$%&()*+,-./:;<=>?@[\]^_`{|}~', '`$&'

But no luck, I know similar to the [uri]escapedatastring, there's a similar one for Regex, but there doesn't appear to be one native for Powershell. I'm sure there is either a [contenttype] that will have a native function to escape the special characters or some way to achieve the end-result.


Solution

  • Because PowerShell's handling of embedded " characters in argument passed to external programs is broken (as of PowerShell 7) - see this answer - you need to manually \-escape " characters embedded in your string:

    $escapedpass = $userpass -replace , '"', '\"'
    

    In the context of your command:

    & .\application.exe --option1 $option1 --user1 $user --password1 ($userpass -replace , '"', '\"')