The Azure Footguns Database
The ways Azure quietly costs you money or exposes you to risk, documented one by one. What it is, why it happens, what it costs, and how to fix it.
Every entry has a stable ID: AZF-0001 is Azure Footgun No. 1. Search or filter by service, category, or ID.
A forgotten DDoS Protection Plan bills ~$2,944/mo while protecting nothing
Network DDoS Protection Plans charge a flat monthly fee even with zero VNets attached. A detached plan is pure waste.
~$2,944/month at list price while unassociated
Key Vault purge protection is off by default, so a deleted vault can be gone for good
Without purge protection, a deleted Key Vault can be permanently purged before the retention window ends, taking the data its keys encrypted with it.
Permanent, unrecoverable loss of keys and secrets if the vault is purged
An unattached managed disk bills its full provisioned size forever
Delete a VM and its data disks usually survive. A managed disk in the Unattached state bills its full provisioned capacity whether or not anything reads it.
~$135/month at list price for a 1 TiB P30 premium SSD doing nothing
A reserved Standard public IP keeps billing after whatever it fronted is gone
Standard SKU public IPs are always statically allocated and always billed. When the load balancer or NIC they fronted goes away, the IP keeps charging.
~$3.65/month at list price per idle Standard static IP
An Azure Bastion bills by the hour even on the days nobody connects
Bastion is billed per deployment-hour, not per session. A host left running in a low-traffic or abandoned VNet charges around the clock for sessions nobody opens.
~$140/month at list price for a Basic SKU, billed hourly regardless of use
An NSG rule allowing 0.0.0.0/0 inbound exposes whatever is behind it to the entire internet
A single inbound allow rule with source Any (0.0.0.0/0) turns whatever sits behind it into a target for the internet's background scanning traffic.
Whatever listens behind the rule is reachable from the entire internet
An idle VPN Gateway with zero tunnels bills ~$140/mo and up, 24/7
A VPN Gateway bills a fixed hourly rate whether or not a single tunnel is up. There is no stopped state, so an idle gateway is pure waste.
~$140/month at list price for a VpnGw1 with zero active connections
An unattached NAT Gateway routes nothing but still bills ~$32/mo base
A NAT Gateway with no subnet associations provides zero outbound connectivity, but its hourly base rate runs 24/7 with no way to pause it.
~$32/month at list price for the base rate alone, before any data processing
An idle Application Gateway serving zero requests still bills ~$144/mo and up
A fully configured Application Gateway left running bills a flat hourly rate even when it serves zero requests. The only ways to end the charge are to stop it or delete it.
~$144/month at list price for a Standard_v2 that serves no traffic
A "Stopped" VM keeps billing full compute; only "Stopped (deallocated)" stops the meter
Shutting a VM down from inside the guest OS leaves it Stopped, not Deallocated. Azure keeps charging full compute, disks, and reserved IPs as if it were running.
the VM's full hourly compute rate, plus disks and reserved IPs, for as long as it sits Stopped
Disk snapshots nobody deletes bill per-GB storage forever
A disk snapshot is a point-in-time copy that never expires on its own. Kept past its useful life, it accrues per-GB storage charges every month until someone deletes it.
~$0.05/GB/month at list price for Standard HDD snapshot storage, indefinitely
An App Service Plan with zero apps still bills its full tier rate
An App Service Plan bills for its reserved compute tier, not for the apps on it. Delete every app and the plan keeps charging the full rate for hosting nothing.
~$55/mo (B1) to ~$146/mo (P1v2) at list price with no apps hosted
A storage account with zero transactions still bills for every GB it holds
A storage account with zero transactions still bills for the data sitting in it. The charge is the stored bytes, not the activity, so an untouched account keeps costing money.
~$0.02/GB/month at list price for stored data: an idle 1 TiB account is ~$20/month for bytes nobody reads
An empty SQL Elastic Pool bills its full provisioned capacity with no databases in it
A SQL Elastic Pool with no databases keeps billing its provisioned eDTU/vCore capacity. The pool charges for the compute it reserves, whether or not a single database sits in it.
~$75–$465/month at list price depending on tier (Basic/Standard/Premium) for a pool with zero databases
An attached NAT Gateway passing zero traffic keeps billing; there is no paused state
A NAT Gateway still wired to a subnet but moving zero bytes and packets keeps billing its hourly base rate. Azure has no way to pause it.
~$32/month at list price for the base resource charge, plus data-processing, even at zero bytes
An ExpressRoute circuit that was never provisioned still bills, and its gateway bills separately
An ExpressRoute circuit that never completed provisioning with a provider bills its full monthly rate anyway, and the gateway you stood up for it bills on top.
$51 to $11,235/month at list price by bandwidth and peering, plus a separate gateway charge
An empty Traffic Manager profile routes nothing and holds a DNS name for no reason
A Traffic Manager profile with no endpoints can resolve nothing, yet it holds a trafficmanager.net name and sits in inventory as finished-looking dead config.
Negligible standalone charge (Traffic Manager has no per-profile fee); the cost is the abandoned config it signals
A Traffic Manager profile with endpoints but zero DNS queries keeps paying for health checks
A profile that still has endpoints but receives zero DNS queries keeps billing per-endpoint health monitoring for a name no client is using anymore.
~$0.36/endpoint/month at list price for health checks that keep running while nobody resolves the name
A Private DNS zone with zero VNet links resolves nothing and still bills
A Private DNS zone needs a virtual network link to answer queries. With zero links it resolves nothing, yet it keeps billing its per-zone base charge.
~$0.50/month per zone at list price, plus query charges, while resolving nothing
A Front Door WAF policy attached to no profile protects nothing and still bills
A Front Door WAF policy only inspects traffic it is linked to. With no security-policy or endpoint links it protects nothing, but it keeps billing its per-policy rate.
~$5-$20/month per policy at list price (classic Front Door WAF) while attached to nothing
An idle Container Registry with zero pulls and pushes bills its tier's daily rate
Azure Container Registry bills a fixed daily rate for its tier regardless of use. A registry with zero pulls and pushes keeps charging as if it were in active service.
~$5/month Basic, ~$20 Standard, ~$50 Premium at list price while idle
An oversized VM runs at single-digit CPU while billing for a SKU the workload never uses
A VM sits at a fraction of its provisioned CPU and memory, so you pay for a SKU far larger than the workload uses. Nothing is broken, so nothing prompts a resize.
~$210/month at list price for the gap between a D8s_v5 and the D2s_v5 the workload actually needs
A single resource's daily spend spikes above its baseline while the subscription budget stays quiet
One resource's daily cost jumps sharply above its normal level. Subscription-total budget alerts don't see it, so the spike inflates the bill until month-end.
The overspend equals the gap between a resource's baseline daily cost and its spiked daily cost, sustained until someone notices
A resource quietly settles into a new, higher cost baseline and the step-up becomes the new normal
A resource's spend steps up to a permanently higher level and stays there. Unlike a spike it never comes back down, so it's easy to accept as the new normal.
The step-up in daily cost, paid every day indefinitely because the new higher level never trips a threshold twice
A storage account with public network access enabled puts its data at the internet edge
Flipping a storage account's public network access from Disabled to Enabled exposes its blob, file, queue, and table endpoints to the whole internet, gated only by keys and identity.
Account endpoints reachable from any network on the public internet
Blob public access turns containers into an anonymous, unauthenticated download link
Setting allowBlobPublicAccess to true lets any container or blob be configured for anonymous reads, so data can be pulled over plain HTTPS with no credentials at all.
Blob data readable with no key, no token, and no identity
An Azure SQL server with public network access enabled exposes the database endpoint to the internet
Enabling public network access on an Azure SQL logical server makes its endpoint resolvable and reachable from the internet, leaving login credentials and firewall rules as the only defense.
SQL server endpoint reachable from the public internet on port 1433
Cosmos DB with public network access enabled puts your database on the internet
A Cosmos DB account with publicNetworkAccess set to Enabled accepts connections from the public internet. A private endpoint does not turn this off.
Every database in the account reachable from any network, gated only by keys
Key Vault with public network access enabled exposes your secrets to any network
A Key Vault with publicNetworkAccess set to Enabled answers requests from the internet. A private endpoint does not disable it.
Secrets, keys, and certificates reachable from the public internet
A Key Vault firewall set to default Allow quietly undoes every network rule you added
A Key Vault whose networkAcls.defaultAction is set to Allow accepts traffic from everywhere. Your carefully built allow-list still exists but no longer gates anything.
Firewall open to all networks; the IP and VNet allow-lists become decorative
A Key Vault with soft-delete disabled makes deleted secrets and keys unrecoverable
A Key Vault with enableSoftDelete set to false has no recovery net. Delete a secret or the vault and it is gone immediately, with no restore.
Deleted or purged secrets, keys, and certificates gone with no recovery window
App Service public network access flipped back on exposes the app to the whole internet
An App Service locked to a private endpoint gets publicNetworkAccess set back to Enabled and the site is answering the public internet again.
App front end reachable from any network, bypassing your private endpoint
Minimum TLS version quietly lowered from 1.2 to 1.0 on Storage, SQL, or App Service
A minimum-TLS setting drops from TLS 1.2 to TLS 1.0 on a storage account, SQL server, or web app, and weak, deprecated transport encryption is allowed again.
Deprecated TLS 1.0/1.1 handshakes accepted on data-plane endpoints
HTTPS-only turned off on a storage account or web app allows cleartext HTTP again
Secure transfer on Storage, or HTTPS-only on App Service, gets switched off and the endpoint starts accepting plaintext HTTP requests.
Data-plane traffic accepted over unencrypted HTTP
Storage infrastructure encryption silently drops your second at-rest layer
Infrastructure (double) encryption adds a second at-rest layer under the standard one. It can only be set at account creation, so once it's off, it stays off.
Removes the second, independent at-rest encryption layer; defense-in-depth is gone
A newly attached public IP quietly puts a resource on the internet
Attaching a public IP to a NIC or load balancer moves a resource from private to internet-facing in one property change, with no separate confirmation.
A previously private resource becomes reachable from the entire internet
Owner held as standing access for months is a permanent blast radius
Owner and User Access Administrator granted as permanent, always-on assignments sit for months. Every day they stand is a day they can be abused.
A high-privilege role held 24/7 for months is a large, always-live blast radius
An Application Gateway with empty backend pools returns silent 502s while billing hourly
An Application Gateway whose backend pools have no targets answers every request with a 502. It keeps billing until someone stops or deletes it, so it charges the whole time it serves errors.
Every request through the gateway fails with HTTP 502 (traffic routed to nothing)
A Load Balancer with an empty backend pool silently drops all inbound traffic
A Load Balancer whose backend pool has no members has nothing to forward to. Connections to its frontend IP are dropped, and the failure is easy to blame on the network.
Inbound traffic to the frontend is dropped; no VM is behind the rule to receive it
A Private Endpoint that is Disconnected or failed provisioning breaks private connectivity while still billing
A Private Endpoint whose connection is Disconnected, or whose provisioning failed, no longer routes to its Private Link service. Anything relying on that private path fails, and the endpoint keeps billing.
Private connectivity to the PaaS resource is broken; traffic over the endpoint silently fails
An unattached NIC costs nothing but leaves stale NSG rules pointing at a ghost
A network interface with no VM, no private endpoint, and no owning resource bills nothing, so it lingers, carrying its old NSG and IP configuration into your security posture as dead weight.
No direct charge; the cost is inventory noise and stale security associations
An orphaned NSG protects nothing and drifts into a misleading audit trail
A network security group associated with no subnet and no NIC enforces nothing, but its rules still show up in every review, quietly implying protection that isn't there.
No direct charge; the cost is unmaintained rules and audit confusion
An unattached route table is free config clutter with zero effect on traffic
A route table associated with no subnet steers no traffic, but its user-defined routes still sit in inventory, inviting confusion about how packets actually flow.
No direct charge; the cost is stale routing config that changes nothing
An empty VNet provides no networking and just complicates your address plan
A virtual network with no subnets provides no networking capability at all, yet it reserves an address space and adds one more thing to reason about in every peering and IP-planning decision.
No direct charge; the cost is a reserved address range and governance clutter
An empty subnet reserves address space and serves no workload
A subnet with no NICs, private endpoints, or delegations carves out address space that nothing uses, quietly shrinking the range available for real workloads.
No direct charge; the harm is wasted address space and network-plan clutter
An empty resource group is dead scaffolding that complicates governance
A resource group that contains nothing still carries tags, RBAC assignments, policy scope, and a place in every report, adding noise no one ever cleans up.
No direct charge; the harm is inventory clutter and misleading governance scope
An orphaned IP Group is a stale allowlist no firewall rule references
An IP Group referenced by no firewall or firewall policy serves no purpose, but it still looks like a live allowlist that engineers assume is enforced.
No direct charge; the harm is a stale, misleading network-security artifact
An orphaned Firewall Policy is a full ruleset that protects nothing
A Firewall Policy attached to no Azure Firewall and inherited by no child policy is a complete ruleset that enforces nothing, yet still reads as authoritative.
No direct charge; the harm is a detailed but unenforced security ruleset
An orphaned API Connection is a stored credential no workflow uses
An API Connection referenced by no Logic App still holds the OAuth token or API key it was authorized with, quietly outliving the workflow it was created for.
No direct charge; the harm is clutter plus stored credentials that outlive their use
An Owner role that only ever reads: over-privileged RBAC no one downgrades
A principal holds Owner but its actual activity is read/deploy work that Contributor or Reader would cover. The extra privilege is pure blast radius with no offsetting use.
Standing Owner/User Access Administrator held by a principal that never manages access
Subscription-wide RBAC for work that lives in one resource group
A Contributor or Owner assignment sits at subscription scope, but every operation the principal performs lands in one resource group. The rest of the subscription is exposed for nothing.
A write role granted at subscription or management-group scope while activity touches a single resource group
A privileged role assignment nobody has used, still standing
A principal holds a privileged role but has performed no operations in its scope. It is standing access with nothing on the other side of the ledger.
A critical or management role granted to a principal with zero activity in that scope
A privileged role assignment keeps full standing access for months after anyone last used it
Privileged access granted for a project or an incident routinely outlives the need. The role keeps full standing access long after anyone last exercised it.
No direct cost; the harm is a persistent, unused privileged foothold and the audit burden it creates
The same role granted separately across 5+ subscriptions signals blanket over-provisioning, not intent
When one principal holds the same role in subscription after subscription, it is usually a blanket grant, not a deliberate per-subscription decision.
No direct cost; the harm is invisible cross-subscription reach and the blast radius of a single compromised principal
A role assignment already covered by a broader grant adds no access, only audit noise
Assigning Reader on a resource group to someone who already has Owner on the subscription grants nothing new. It just clutters every access review.
No direct cost and no added access; the harm is inflated access reviews and obscured least-privilege analysis
An underutilized Azure reservation burns its committed spend silently, hour after hour
You pre-paid for capacity you aren't using. A reservation running below its utilization threshold burns committed dollars silently every hour, and Azure never rolls the unused hours forward.
the unused share of the commitment — e.g. ~$4,000/month on a $10,000/month reservation running at 60% utilization
A reservation expires silently and every covered VM snaps back to pay-as-you-go overnight
A reservation quietly reaches the end of its term and every covered resource reverts to pay-as-you-go rates overnight. The bill jump lands before anyone connects it to the lapse.
loss of the reservation discount (commonly 30–60% at list price) on every covered resource, starting the hour the term ends
Regional vCPU quota fills invisibly until a deploy, scale-out, or DR failover fails with QuotaExceeded
vCPU quotas are per subscription, per region, per VM family — and nothing warns you as they fill. The first symptom is a QuotaExceeded error on the day a deployment, scale-out, or failover actually mattered.
blocked deployments, failed autoscale events, and DR failovers that cannot allocate VMs — with hours-to-days of lead time to raise the limit
A storage firewall set to default Allow leaves every network path to the account open
A storage account whose networkAcls.defaultAction is Allow accepts traffic from every network. The firewall exists, the rule list looks reassuring, and none of it filters anything.
Account reachable from every network; the configured IP and VNet rules gate nothing
Shared key authorization lets anyone holding a storage account key bypass Entra ID entirely
Every storage account is born with two account keys and shared key authorization enabled. Anyone holding a key gets full data-plane access — no Entra ID, no RBAC, no Conditional Access, no name in the logs.
Either of two static account keys grants full data-plane access with no identity attached
Cross-tenant replication left enabled lets a storage account copy blobs into someone else's tenant
With allowCrossTenantReplication enabled, an object replication policy can name a destination account in a completely different Entra tenant — a data-movement channel that looks like a legitimate Azure feature because it is one.
Replication policies may continuously copy blobs to a storage account in another Entra tenant
A general-purpose v1 storage account runs production data on a retired-in-2026 account model
General-purpose v1 accounts predate blob access tiers, lifecycle management, and a decade of security and pricing evolution. Microsoft has scheduled their retirement for 2026 — accounts left behind get migrated on Microsoft's timetable, not yours.
Little or no direct cost today; a deprecated account model missing tiering, lifecycle policies, and modern controls, with forced migration coming in 2026
Key Vault legacy access policies: a parallel permission system your RBAC reviews never see
Vaults created without enableRbacAuthorization manage permissions through a per-vault access-policy list that RBAC tooling, access reviews, and PIM never touch.
No direct cost — an unaudited parallel permission model on the resource that holds your secrets
Cosmos DB master keys are on by default — full account access outside Entra ID and RBAC
Every Cosmos DB account ships with two master keys enabled. A key in a connection string is full access to all the data — no Entra ID, no RBAC, no conditional access, no per-user audit trail.
Anyone holding either account key has full data-plane read/write on every database in the account, with no identity attached
A multi-region Cosmos DB account with automatic failover off still needs a human during the outage
You pay for a second Cosmos DB region so an outage can't take you down. With automatic failover disabled, it still can — promotion of the read region waits for someone to click the button.
Write downtime for the length of a regional outage plus however long it takes a human to notice, decide, and trigger failover
A container registry with public network access enabled exposes your image supply chain to the internet
The registry that feeds your production clusters accepts connections from any internet address. Authentication becomes the only barrier between the world and the images everything runs on.
Registry endpoint reachable from any address on the public internet
The ACR admin user is one shared credential with full push and pull over every image
The ACR admin account is a single shared username/password with full push and pull rights and no identity behind it. It ends up pasted into CI configs everywhere, and a leak means someone else decides what your clusters run.
One static credential grants full push and pull across the entire registry, with no identity attached
Anonymous pull enabled: anyone on the internet can download your container images
With anonymous pull enabled, unauthenticated clients can download images from the registry. Images carry baked-in config, internal hostnames, and more often than anyone admits, credentials.
Images downloadable by unauthenticated clients, including baked-in config, internal hostnames, and the occasional secret
An internet-reachable Azure Cache for Redis puts live session tokens one leaked key from exposure
A cache that usually holds session tokens and hot application data is reachable from the internet, and an access key is the only thing standing in the way.
Session tokens, auth state, and cached data reachable from any internet address, with an access key as the only barrier
Redis non-SSL port 6379 enabled: cache traffic and the access key cross the network in cleartext
Plaintext port 6379 is open alongside the TLS port. Every GET and SET, session tokens included, crosses the network unencrypted, and so does the access key during AUTH.
Every command, every cached value, and the cache access key itself readable by anyone positioned on the network path
A PostgreSQL flexible server on a public endpoint leaves IP firewall rules as the only barrier to your data
The Postgres server answers on a publicly resolvable endpoint. Firewall rules, plain IP allow-lists with no identity behind them, are the only thing between your data and the internet.
The database answers the internet on port 5432; identity-free IP allow-list rules are the only network barrier
A MySQL flexible server with public network access is one weak firewall rule from the open internet
The MySQL flexible server sits on a public endpoint guarded only by IP firewall rules, and the creation-time connectivity choice can't simply be swapped out later.
A publicly resolvable database endpoint on port 3306, reachable by anything a firewall rule lets through, with no identity check at the network layer
An AKS cluster's public API server puts the Kubernetes control plane on the internet
The default AKS deployment gives the Kubernetes API server a public endpoint with no IP restrictions. The API that can read every secret and exec into every pod is reachable from anywhere.
The cluster's admin API reachable from any internet address, with credentials as the only barrier
AKS local accounts hand out a cluster-admin kubeconfig that bypasses Entra ID
Local accounts are enabled on AKS by default. Anyone with the right Azure role can pull an admin kubeconfig that works with no identity attached, ignores conditional access, and keeps working after they leave.
A static cluster-admin credential outside Entra ID, conditional access, and central revocation
An AKS cluster with Kubernetes RBAC disabled makes every credential cluster-admin, and only a rebuild fixes it
With enableRBAC: false there is no in-cluster authorization at all: every kubeconfig, service account token, and pipeline credential is effectively cluster-admin. And RBAC cannot be enabled on an existing cluster.
Every credential that can reach the API server has full control of every namespace and workload
An AKS cluster with no network policy engine lets one compromised pod reach every other pod
Unless you choose a network policy engine at cluster creation, AKS enforces none. Kubernetes NetworkPolicy resources are silently ignored and the pod network is completely flat.
Unrestricted pod-to-pod traffic: one compromised container can reach every workload in the cluster
A managed disk open to public export is one SAS URL from full disk exfiltration
Managed disks default to AllowAll network access with public export enabled. One export SAS turns the entire disk into a downloadable file, no VM login required.
A single export SAS downloads the raw VHD — OS, data, credentials, everything on the disk — from anywhere on the internet
A VM without Trusted Launch has no Secure Boot or vTPM — rootkits load below your EDR
Trusted Launch brings Secure Boot and vTPM to Azure VMs at no extra cost, but plenty of deployment paths still create Standard VMs where the entire boot chain runs unverified.
Boot-level malware loads before the OS and its security agents — nothing running inside the VM can see or stop it
Boot diagnostics disabled: when the VM won't start, you're debugging a black box
Boot diagnostics is off unless someone turned it on, and you discover that at the worst possible moment: mid-outage, staring at a VM that won't boot and produces no evidence about why.
A boot failure with no console screenshot or serial log — recovery becomes guesswork while the outage clock runs
A VM still on unmanaged OS disks runs a retired storage model Azure can stop and deallocate
Unmanaged VHD disks were fully retired on March 31, 2026. A VM still booting from one is running on borrowed time, outside modern snapshot, encryption, and reliability tooling.
Little direct cost; the VM sits on a fully retired storage model that Azure can stop, deallocate, and refuse to restart
A Linux VM accepting SSH passwords puts brute-forceable credentials on the internet's most attacked port
The Linux VM was deployed with disablePasswordAuthentication set to false, so sshd accepts passwords: guessable, reusable, phishable credentials with no MFA in front of them.
One guessed or reused password is an interactive shell on the VM; port 22 is brute-forced around the clock
An Event Hubs namespace with public network access enabled puts your event stream at the internet edge
Event Hubs namespaces allow traffic over the public network by default. The stream carrying your telemetry and business events is reachable from anywhere, and authentication is the only gate.
Namespace endpoints (AMQP, Kafka, HTTPS) reachable from any network on the public internet, gated only by keys and identity
Event Hubs SAS keys are on by default: a connection string is full access to the stream, no identity required
Every Event Hubs namespace ships with SAS-key authentication enabled. The keys are long-lived static secrets that bypass Entra ID and conditional access, and they live in connection strings scattered through configs.
Anyone holding a namespace-level SAS key can read, replay, and inject events across the namespace, with no identity attached
A Service Bus namespace with public network access enabled leaves your message broker answering the internet
Service Bus namespaces allow public network traffic by default. The broker gluing your systems together, and every in-flight order, job, and event sitting in its queues, is reachable from anywhere.
Every queue and topic in the namespace reachable from any network on the public internet, gated only by keys and identity
Service Bus SAS keys are on by default: one connection string can read, inject, and delete your queues
Every Service Bus namespace ships with SAS-key authentication enabled, and the root key grants manage rights over the whole namespace. Those keys live in connection strings, and a connection string is not an identity.
Anyone holding a namespace-level SAS key can receive, send, and manage messages across every queue and topic, with no identity attached
An Azure OpenAI account with public network access enabled leaves API keys as the only lock on your models and data
Your Azure OpenAI or AI services account is reachable from the internet, so an API key is the only thing standing between the world and your models, your quota, and any data your prompts carry.
Model endpoints, quota, and any data sent in prompts reachable from any network on the internet
An Azure AI Search service with public network access enabled puts your whole RAG corpus behind one query key
The search index is usually the retrieval layer of a RAG pipeline, holding full copies of the documents it ingested. A public endpoint makes one leaked key equal to the whole corpus.
Every indexed document reachable from any network, gated only by API keys and optional IP rules
A SignalR or Web PubSub service with public network access enabled takes realtime connections from anywhere
The realtime channel pushing live data to your users' browsers accepts connections from any internet address. Access keys and tokens are the whole boundary, and the default is Enabled.
The realtime message plane reachable from any network, gated only by access keys and tokens
An App Service with no managed identity runs on secrets that leak, sprawl, and never expire
An App Service without a managed identity authenticates to databases, storage, and Key Vault with connection strings and keys in app settings — a whole credential class Azure would let you delete.
Every downstream connection is a copyable long-lived secret; one leaked connection string is full data-plane access with no identity attached
A Standard-SKU Application Gateway load-balances attacks as happily as legitimate traffic
An Application Gateway on the Standard SKU terminates TLS and routes requests but inspects nothing. SQL injection and XSS pass through it exactly like a login page does.
A layer-7 entry point with zero payload inspection; OWASP-class attacks are routed straight to the backend
A WAF policy stuck in Detection mode logs every attack and blocks none of them
Azure WAF policies start life in Detection mode, which monitors and logs matching requests but blocks nothing. The flip to Prevention is a manual step that routinely never happens.
The WAF is visibility only: matched attacks are written to the logs and delivered to the backend anyway
A subnet with no NSG leaves every workload in it with zero network filtering
Azure does not require an NSG on a subnet. Without one there is no subnet-level network filter at all, and every workload inside relies entirely on whatever other controls happen to exist.
No subnet-level inbound or outbound filtering for anything deployed there; one public IP or one compromised neighbor reaches every workload in the subnet
A VNet peering stuck outside the Connected state silently black-holes cross-network traffic
VNet peering is two resources, one on each network, and both must exist for traffic to flow. Create only one side, or delete one side later, and the survivor sits there carrying nothing.
Cross-VNet traffic on that path is dropped until the peering is repaired; hub-and-spoke workloads lose their route to shared services
An NSG public-IP allowlist on SSH, RDP, or database ports is still a management port on the internet
Allow-listing the office IP for SSH or RDP feels like the responsible version of an open port. It's better than 0.0.0.0/0, and it still puts an identity-less protocol on the internet behind addresses that rot.
Management and database ports reachable from the public internet, gated only by a hand-maintained list of IPs with no identity, MFA, or expiry behind it
A service principal with Owner at subscription scope is one leaked secret from full compromise
An automation identity holding Owner or Contributor across the whole subscription is a standing, non-interactive credential with a subscription-sized blast radius, and PIM can't help it.
Whoever holds the SP's secret holds the whole subscription: create, modify, delete anything, and for Owner, grant further access
A PIM eligibility nobody activates is a dormant escalation path your access reviews miss
An eligible assignment on a privileged role that hasn't been activated in months isn't hygiene, it's a live escalation path the principal (or whoever compromises it) can exercise any time.
The principal can assume Owner or Contributor at that scope at any time; a dormant eligibility is privilege waiting to be claimed
RDP, SSH, or a database port open to the internet: the misconfiguration bots find in minutes
An NSG inbound Allow rule from 0.0.0.0/0 on RDP, SSH, or a database port is the most exploited misconfiguration class in Azure. Automated scanners find it in minutes, not weeks.
Brute-force and known-CVE exposure on identity-less protocols; internet-wide scanners find a newly opened port within minutes
Stop hunting these one at a time
Every footgun in this database, checked on every scan, inside your own tenant. You find out from a report, not from the bill.
Available now on the Azure Marketplace.
Not ready to install anything? Browse the Azure Footguns Database: 55+ documented ways Azure quietly costs money or creates risk.
StratoLens catches the cost waste, access risk, and config drift across your whole Azure estate, from inside your own tenant, so your data never leaves it.