What it is
A Service Bus namespace that still accepts shared access signature (SAS) key authentication, the default on every namespace. The auto-created RootManageSharedAccessKey policy grants manage, send, and listen rights over every queue and topic, and its key authenticates whoever presents it, from wherever they present it. SAS keys are long-lived static secrets that cannot be conditionally gated and carry no identity, so they sit outside everything Entra ID, RBAC, and conditional access enforce. Until disableLocalAuth is set to true, the keys remain a parallel access path your identity controls never see.
Why it happens
Key auth is the historical Service Bus model and still the path of least resistance: the portal offers "Connection strings" on every namespace, decades of samples and libraries expect one, and dropping it into an app setting makes the integration work in minutes. disableLocalAuth defaults to false, and the create flow never mentions it.
Messaging makes the sprawl worse than most services. A broker by definition has many senders and many receivers, often owned by different teams, and the expedient move is to hand each of them the same connection string. Rotating the key then means coordinating a simultaneous change across every one of those systems, so the key effectively never rotates.
The way out is the same two-step as the other local-auth footguns: move senders and receivers to Entra ID auth (managed identities plus the Service Bus Data Sender and Data Receiver roles), then set disableLocalAuth: true so the old keys stop working. Only the second step retires the standing secret.
What it costs / blast radius
A connection string in a committed repo, a CI log, or an old wiki page is identity-free control of the namespace. An attacker can receive (and thereby destructively remove) messages from queues, silently subscribe to topics, or inject forged messages that downstream systems execute as trusted commands: create the order, issue the refund, provision the account. Message injection is uniquely dangerous because consumers almost never authenticate individual messages; the queue itself is the trust boundary. And since a key is not an identity, you cannot revoke one holder or trace who did what, only rotate the key for everyone at once. (Authored assessment of Azure behavior, not a measured statistic.)
See it
resource sbns 'Microsoft.ServiceBus/namespaces@2024-01-01' = {
name: 'sbns-orders-prod'
location: location
sku: { name: 'Standard', tier: 'Standard' }
properties: {
// disableLocalAuth omitted — the root SAS key grants
// manage/send/listen on every queue and topic
}
}resource sbns 'Microsoft.ServiceBus/namespaces@2024-01-01' = {
name: 'sbns-orders-prod'
location: location
sku: { name: 'Standard', tier: 'Standard' }
properties: {
disableLocalAuth: true // SAS keys no longer authenticate
}
}
// Data-plane access via Azure RBAC instead. App code switches to
// DefaultAzureCredential — no connection string to leak.
resource receiveRole 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
name: guid(sbns.id, workerPrincipalId, 'sb-data-receiver')
scope: sbns
properties: {
// Built-in "Azure Service Bus Data Receiver" role
roleDefinitionId: subscriptionResourceId(
'Microsoft.Authorization/roleDefinitions',
'4f6d3b9b-027b-4f4c-9142-0e5a2a2247e0')
principalId: workerPrincipalId
}
}How StratoLens helps
StratoLens continuously flags every Service Bus namespace where SAS-key auth is still enabled, across all your subscriptions, inside your own tenant. You see at a glance which brokers still treat a leaked connection string as a valid credential, without auditing namespaces by hand.