Back to blog
AzureBest PracticesCloud SecurityIdentity & AccessNetworking

Key Vault Does Not Allow Trusted Microsoft Services Bypass

Learn why an Azure Key Vault firewall set to Deny breaks platform services when the trusted Microsoft services bypass is off, and how to fix it safely.

TL;DR

This check flags Key Vaults whose network firewall does not allow trusted Microsoft services to bypass it. Without the bypass, Azure platform services like Disk Encryption, Backup, and App Service can fail to read secrets or keys. Turn on the bypass with --bypass AzureServices while keeping --default-action Deny.

Locking down an Azure Key Vault with network rules is the right instinct. You set the default action to Deny, whitelist a few VNets and IP ranges, and your secrets are no longer reachable from the public internet. The problem is that a strict deny rule does not just block attackers, it also blocks the Azure platform services that legitimately need to reach the vault. The keyvault_notrustedservices check catches the specific case where the network ACL denies traffic but the trusted Microsoft services bypass is turned off.

This is a subtle one. The vault looks secure, the firewall is on, and everything passes a quick glance. Then a disk encryption rotation silently fails or a backup job can't unwrap a key, and you are left debugging an access problem that has nothing to do with RBAC or access policies.


What this check detects

Every Key Vault has a networkAcls object that controls firewall behavior. Two fields matter here:

  • defaultAction — either Allow (open) or Deny (locked down to whitelisted sources).
  • bypass — either AzureServices (trusted Microsoft services can bypass the firewall) or None (no exceptions).

The check fires when the firewall is restrictive but the bypass is set to None. In JSON, a failing configuration looks like this:

{
  "properties": {
    "networkAcls": {
      "defaultAction": "Deny",
      "bypass": "None",
      "ipRules": [],
      "virtualNetworkRules": []
    }
  }
}

Note: The "trusted Microsoft services" bypass is not a blanket exception for all of Azure. It applies to a curated list of first-party services that authenticate to your vault and that Microsoft has vetted, such as Azure Backup, Azure Disk Encryption, Azure App Service, and Event Grid. Those services still need a valid Key Vault access policy or RBAC role assignment to read anything. The bypass only handles the network layer.


Why it matters

The risk here is not a direct security hole, it is an operational failure that often masquerades as one. When the bypass is off and the default action is Deny, several common Azure workflows break:

  • Azure Disk Encryption cannot fetch the key encryption key, so VM provisioning or key rotation fails.
  • Azure Backup cannot access keys needed to back up encrypted resources.
  • App Service and Functions referencing Key Vault secrets in app settings get blank values or startup errors.
  • Azure SQL and Storage using customer-managed keys lose access to the wrapping key, which can render data unreadable until access is restored.

That last point is the dangerous one. If a storage account or database uses a customer-managed key (CMK) stored in a vault that suddenly blocks the platform, the encrypted data becomes inaccessible. The service shows the volume as unavailable until the network path is restored. People discover this during incident response, which is the worst possible time.

Warning: Turning the bypass off on a vault that holds customer-managed keys for Storage or SQL can take encrypted data offline within hours, once the service's cached key handle expires. Always confirm what depends on a vault before tightening its firewall.

It is worth being precise about the trade-off. Enabling the trusted services bypass does slightly widen the network surface, because it lets Microsoft-operated services reach the vault from outside your whitelisted networks. But those services cannot read a single secret without an access grant, and the alternative, leaving the bypass off, frequently pushes teams to set defaultAction back to Allow out of frustration. That is far worse. A vault with the bypass on and Deny as the default is more secure than a vault left wide open.


How to fix it

The fix is to enable the AzureServices bypass while keeping your restrictive default action and existing whitelist rules intact.

Azure CLI

Check the current state first:

az keyvault show \
  --name my-vault \
  --query "properties.networkAcls" \
  -o json

Then update the network ACL to allow the trusted services bypass:

az keyvault update \
  --name my-vault \
  --resource-group my-rg \
  --bypass AzureServices \
  --default-action Deny

Tip: Setting --bypass AzureServices does not touch your IP rules or VNet rules. You can run this on a production vault without re-adding your existing whitelist, since the update only modifies the fields you pass.

Azure Portal

  1. Open the Key Vault and go to Settings → Networking.
  2. On the Firewalls and virtual networks tab, confirm public access is set to Allow public access from specific virtual networks and IP addresses (this is the Deny-by-default mode).
  3. Under the exception list, check the box for Allow trusted Microsoft services to bypass this firewall.
  4. Click Apply.

Terraform

In the azurerm_key_vault resource, set bypass to AzureServices inside the network_acls block:

resource "azurerm_key_vault" "main" {
  name                = "my-vault"
  resource_group_name = azurerm_resource_group.main.name
  location            = azurerm_resource_group.main.location
  tenant_id           = data.azurerm_client_config.current.tenant_id
  sku_name            = "standard"

  network_acls {
    default_action = "Deny"
    bypass         = "AzureServices"
    ip_rules       = ["203.0.113.0/24"]

    virtual_network_subnet_ids = [
      azurerm_subnet.app.id
    ]
  }
}

Bicep

resource vault 'Microsoft.KeyVault/vaults@2023-07-01' = {
  name: 'my-vault'
  location: location
  properties: {
    tenantId: tenant().tenantId
    sku: {
      family: 'A'
      name: 'standard'
    }
    networkAcls: {
      defaultAction: 'Deny'
      bypass: 'AzureServices'
      ipRules: [
        {
          value: '203.0.113.0/24'
        }
      ]
      virtualNetworkRules: []
    }
  }
}

How to prevent it from happening again

One-off fixes drift back over time, especially when a new vault is spun up by hand or a module default gets overridden. Bake the requirement into the places where vaults are created and audited.

Azure Policy

Azure Policy can audit or deny vaults that have a restrictive firewall but the bypass turned off. Here is a policy rule that flags non-compliant vaults:

{
  "if": {
    "allOf": [
      {
        "field": "type",
        "equals": "Microsoft.KeyVault/vaults"
      },
      {
        "field": "Microsoft.KeyVault/vaults/networkAcls.defaultAction",
        "equals": "Deny"
      },
      {
        "field": "Microsoft.KeyVault/vaults/networkAcls.bypass",
        "notEquals": "AzureServices"
      }
    ]
  },
  "then": {
    "effect": "audit"
  }
}

Start with audit to measure your fleet, then move to deny once you have cleaned up existing vaults and confirmed nothing legitimate breaks.

Tip: Assign the policy at the management group level so every subscription inherits it. New vaults created in any team's subscription get evaluated automatically, no per-subscription setup needed.

CI/CD gate with policy-as-code

If your infrastructure lives in Terraform, catch this before it ships using a tool like Checkov or OPA/Conftest in your pipeline. A small Conftest policy keeps the rule readable:

package main

deny[msg] {
  resource := input.resource.azurerm_key_vault[name]
  acl := resource.network_acls[_]
  acl.default_action == "Deny"
  acl.bypass != "AzureServices"
  msg := sprintf("Key Vault '%s' denies traffic but does not allow trusted Microsoft services bypass", [name])
}

Wire it into the plan stage so a pull request that introduces a misconfigured vault fails before merge.


Best practices

  • Default to Deny, bypass to AzureServices. This pairing is the baseline for any production vault. Restrictive network posture, platform integrations still work.
  • Prefer private endpoints for app traffic. The trusted services bypass handles Microsoft platform access, but your own applications should reach the vault over a private endpoint rather than relying on IP allowlists, which are brittle and leak across environments.
  • Keep access policies and RBAC tight. The network bypass is not an authorization grant. Make sure each service only has the access policy or role it actually needs, and use RBAC over the legacy access policy model on new vaults.
  • Document what depends on each vault. Before changing firewall settings, know which storage accounts, databases, and backup jobs reference the vault's keys. A simple tag or wiki page saves you from a CMK outage.
  • Enable logging. Turn on Key Vault diagnostic logs and route them to Log Analytics. Denied requests show up clearly, which turns a mysterious failure into a five-minute query.

Note: If you run a vault that genuinely has no Microsoft platform dependencies and only your own private-endpoint traffic, leaving the bypass off is a defensible choice. The check exists because that situation is rare, and the far more common cause of a disabled bypass is an oversight that breaks platform services. Treat a finding here as a prompt to confirm intent, not as a mandate.

The short version: a Key Vault firewall set to Deny is good security, but it has to coexist with the Azure services that depend on the vault. The trusted Microsoft services bypass is how you get both. Turn it on, keep your default action restrictive, and back it with policy so the setting survives the next round of vault creation.