secureString parameter has a hardcoded default

Remove secret defaults from secureString parameters and supply values through a protected deployment path.

Description

ARM secureString parameters and Bicep's @secure() protect parameter values from ordinary deployment-history exposure. However, a password or key written as a default remains visible to anyone who can read the template or its repository history.

Marking a parameter as secure does not protect a secret embedded in source code.

Potential impact

  • People who can access the template or repository history may obtain the secret.
  • Reusing the same secret across environments can expand the impact of exposure.

Remediation

  • Remove defaults containing secrets and supply values at deployment through Key Vault references or protected pipeline variables. Do not print them or write them to ordinary logs.
  • Rotate exposed secrets, update their consumers and invalidate the old values. Deleting a value from the current file does not remove exposure in repository history.
  • Limit deployment and secret-reading permissions to the identities that need them, and verify the protected input path.

Examples

Provide the SQL server name and administrator account for your environment. The password must meet service complexity requirements; configure networking and access permissions separately.

Before

bicep
@secure()
param adminPassword string = 'HardcodedPassword1!'
param adminLogin string
param sqlServerName string

resource sqlServer 'Microsoft.Sql/servers@2015-05-01-preview' = {
  name: sqlServerName
  location: resourceGroup().location
  tags: {}
  properties: {
    administratorLogin: adminLogin
    administratorLoginPassword: adminPassword
    version: '12.0'
  }
}

HardcodedPassword1! remains in the source code. Do not use it as a real secret.

After

bicep
@secure()
param adminPassword string
param adminLogin string
param sqlServerName string

resource sqlServer 'Microsoft.Sql/servers@2015-05-01-preview' = {
  name: sqlServerName
  location: resourceGroup().location
  tags: {}
  properties: {
    administratorLogin: adminLogin
    administratorLoginPassword: adminPassword
    version: '12.0'
  }
}

Removing the default requires a value at deployment. Obtain that value through a protected path and keep it out of logs and source code.

References