SecureString holds sensitive text during PowerShell automation so credentials, API keys, and similar values need not be kept as ordinary plain-text strings. It is commonly paired with PSCredential objects and secret stores when scripts authenticate to services across environments. section 4.2 section 4.6
Ordinary string changes can leave copies in memory even after a variable is cleared. A SecureString is pinned rather than copied and is encrypted in memory on Windows, limiting what a memory dump can read and tying removal to variable deletion or process end. This protection is not equivalent on Linux or macOS: the type can be used there, but its in-memory values are not encrypted. section 4.2.1
Create and handle SecureString values with the exposure path in mind:
- Prompt interactively with Read-Host -AsSecureString when a user can enter the value at run time. section 4.2.1
- Convert an existing string with ConvertTo-SecureString -AsPlainText -Force only when necessary. The source plain text has already existed in memory and may be recorded in script content, event logs, or PowerShell history. section 4.2.1
- Expect default exported values to be tied to a user and device. Use a custom encryption key when portability between computers is required. section 4.2.1
Prompt for a secret
Use a prompt when an automation can obtain the secret from its operator rather than embedding it in a script: $SecureString = Read-Host -AsSecureString The resulting value is a System.Security.SecureString, not a normal string. section 4.2.1
SecretManagement normally returns string secrets as SecureString objects. Request -AsPlainText only for values that a downstream command expects as ordinary text, such as a server name or email address; keep credentials in their secure form where supported. section 4.4.1
Listing 4.4 SQL health check through Jenkins
$secure = @{ #1
String = $ENV:sqlpassword
AsPlainText = $true
Force = $true
}
$Password = ConvertTo-SecureString @secure
$SqlCredential = New-Object System.Management.Automation.PSCredential `
($ENV:sqlusername, $Password)
$SQLServer = $ENV:sqlserver #2
$DbaDiagnosticQuery = @{
SqlInstance = $SQLServer
SqlCredential = $SqlCredential
QueryName = 'DatabaseProperties'
}
$HealthCheck = Invoke-DbaDiagnosticQuery @DbaDiagnosticQuery
$failedCheck = $HealthCheck.Result |
Where-Object { $_.'Recovery Model' -ne 'SIMPLE' }
if ($failedCheck) {
$From = $ENV:sendgrid #2
$secure = @{ #1
String = $ENV:sendgridusername
AsPlainText = $true
Force = $true
}
$Password = ConvertTo-SecureString @secure
$Credential = New-Object System.Management.Automation.PSCredential `
($ENV:sendgridpassword, $Password)
$Body = $failedCheck | ConvertTo-Html -As List |
Out-String
$EmailMessage = @{
From = $From
To = $SendTo
Credential = $EmailCredentials
Body = $Body
Priority = 'High'
Subject = "SQL Health Check Failed for $($SQLServer)"
SendGrid = $true
}
Send-EmailMessage @EmailMessage
}
Jenkins injects credential values as ordinary environment-variable strings, so rebuild the password as a SecureString before constructing a PSCredential for the SQL connection. section 4.4.2
