Guidance for applications using the Key Vault libraries

Heath Stewart

The Azure SDK team has become aware of a potential risk for developers using the Key Vault libraries. Most applications using the Key Vault libraries are safe; however, applications that take user-provided URIs to Key Vault or Managed HSM resources like secrets, keys, or certificates may leak authentication information. User-provided URIs should be validated correctly to mitigate potential leaks.

Applications should validate URIs as recommended below, and in addition, the Azure SDK team is releasing new Key Vault libraries to provide some defense in depth.

Affected applications

Applications that accept user-provided URIs for a customer-owned Azure Key Vault or Azure Managed HSM should validate the URIs. Examples include, but aren’t limited to:

  • URIs to keys for encryption at rest, often referred to as custom-managed keys (CMK).
  • URIs to secrets to configure an application, including API keys, connection strings, etc.

URIs could be provided through configuration files, command line interfaces (CLIs), or user interfaces. If the URIs aren’t properly validated, an attacker may be able to trick your application into giving up an Azure Active Directory (Azure AD) access token for another Azure service, or to use keys and secrets from another source.

All applications accepting user-provided URIs should perform the following steps to validate a Key Vault or Managed HSM URI:

  • The URI must be a well-formed absolute URI.
  • The URI scheme must be HTTPS.
  • The URI host domain must match one of the known domain names for Key Vault or Managed HSM.

Azure Key Vault and Managed HSM use the same pattern for host names: typically, a customer-selected name followed by the Azure cloud-specific domain name for the service; however, Managed HSM may use multi-level names for region support. Name testing should use the Key Vault and Managed HSM domain suffixes prepended with the “.” character to confirm a match and to block abuse such as “maliciousvault.azure.net”, since this URI wouldn’t match “.vault.azure.net”. The domain names for Key Vault and Managed HSM depend on the cloud your application uses. Currently, there’s no single, trusted source for these domain names so you’ll either need to hardcode or configure them. You can get an up-to-date list of Key Vault and Managed HSM domain names using the Azure CLI, which currently prints the following information:

az cloud list --query '[].{name:name,KeyVault:suffixes.keyvaultDns,ManagedHSM:suffixes.mhsmDns}' -o table
Name KeyVault ManagedHSM
AzureCloud .vault.azure.net .managedhsm.azure.net
AzureChinaCloud .vault.azure.cn .managedhsm.azure.cn
AzureUSGovernment .vault.usgovcloudapi.net .managedhsm.usgovcloudapi.net
AzureGermanCloud .vault.microsoftazure.de .managedhsm.microsoftazure.de

Though affected applications should validate user-provided URIs reference valid Key Vault and Managed HSM hosts, Azure Key Vault libraries have been updated to make sure the resource in the challenge matches the given host domain as described above. You should update your applications to use any of the packages below or newer:

The library updates alone don’t completely mitigate the issue but do prevent a malicious user-provided URI from using the authentication challenge to request an access token for another Azure service since the resource wouldn’t match the host domain. We believe this change will affect few applications that don’t connect directly to Key Vault or Managed HSM; however, if your application is broken by this change in default behavior, in addition to validating any user-provided URIs as described above you can disable this feature:

.NET

var vaultUri = new Uri("https://myvault.vault.azure.net");
var credential = new DefaultAzureCredential();
var options = new SecretClientOptions()
{
    DisableChallengeResourceVerification = true
};
var client = new SecretClient(vaultUri, credential, options);

C++

The Azure Key Vault libraries for C++ always use the user-provided vaultUrl domain for the scope and cannot be changed currently.

Go

vaultURL := "https://myvault.vault.azure.net"
credential, err := azidentity.NewDefaultAzureCredential(nil)
options := azsecrets.ClientOptions{
    DisableChallengeResourceVerification: true,
}
client := azsecrets.NewClient(vaultURI, credential, &options)

Java

String vaultUrl = "https://myvault.vault.azure.net";
String credential = new DefaultAzureCredentialBuilder().build();
SecretClient secretClient = new SecretClientBuilder()
    .vaultUrl(vaultUrl)
    .credential(credential)
    .disableChallengeResourceVerification()
    .buildClient();

JavaScript

const vaultUrl = "https://myvault.vault.azure.net";
const credential = new DefaultAzureCredential();
const client = new SecretClient(vaultUrl, credential, {
    disableChallengeResourceVerification: true
});

Python

vault_url = "https://myvault.vault.azure.net"
credential = DefaultAzureCredential()
client = SecretClient(
    vault_url=vault_url,
    credential=credential,
    verify_challenge_resource=False
)

Summary

Make sure your application validates all user-provided URIs to Key Vault or Managed HSM resources like secrets, keys, or certificates to avoid potential leaks of authentication information. Update your Key Vault libraries to the latest package versions for additional defense, which you can disable if this new feature breaks your application.