This check flags Azure subscriptions with zero Azure Policy assignments, meaning nothing is enforcing or auditing your resource configurations. Assign at least a baseline initiative like the Azure Security Benchmark so misconfigurations get caught automatically.
Azure Policy is the guardrail layer of your subscription. When it is empty, every resource your teams deploy goes unchecked: public storage accounts, unencrypted disks, VMs with open management ports, databases without auditing. Nothing stops them and nothing reports on them. The No Policy Assignments check catches exactly this situation, a subscription running without any governance rules in place.
This is one of those findings that looks benign on a fresh subscription but becomes a serious problem the moment real workloads land in it. Let's break down what it means and how to close the gap.
What this check detects
The policy_noassignment check queries the Azure Policy assignments at the subscription scope and reports a finding if it returns an empty list. In plain terms: there are no policies assigned to the subscription, and therefore no automated enforcement or auditing of your resource configurations.
Azure Policy works through two pieces:
- Policy definitions describe a condition and an effect, for example "audit any storage account that allows public blob access."
- Policy assignments attach a definition (or a grouped set of definitions called an initiative) to a scope such as a management group, subscription, or resource group.
A definition does nothing until it is assigned. You can have hundreds of built-in definitions available in your tenant, but if none of them are assigned to your subscription, Azure Policy is effectively switched off there. That is what this check flags.
Note: Azure ships with over a thousand built-in policy definitions and dozens of initiatives. They are available to assign at any time but are not active by default. An empty subscription is the normal starting state, not a misconfiguration Azure creates on your behalf.
Why it matters
Without policy assignments you lose the only native, automatic mechanism for keeping resources within your security and compliance baseline. The risk shows up in a few concrete ways.
Misconfigurations ship unnoticed
Policy can use the audit effect to flag risky resources and the deny effect to block them at creation time. With no assignments, both are gone. An engineer can create a storage account with public network access, a SQL database without Transparent Data Encryption, or a VM with RDP open to the internet, and nothing will warn you. These are the configurations attackers scan for constantly.
Compliance drift is invisible
Frameworks like CIS Azure, PCI DSS, ISO 27001, and the Microsoft Cloud Security Benchmark map directly to policy initiatives. The Azure compliance dashboard derives its score from assigned initiatives. With nothing assigned, your compliance dashboard is blank, and you have no evidence trail for auditors that controls are even being measured.
No automated remediation
Policies with the deployIfNotExists and modify effects can fix problems for you, for example deploying diagnostic settings to every new resource or enabling encryption automatically. Without assignments, every remediation becomes manual work that someone has to remember to do.
Warning: An empty subscription today does not stay empty. Subscriptions get reused, handed to new teams, and filled with production workloads. A governance gap that is harmless on day one becomes a real exposure the moment someone deploys into it without realizing the guardrails were never there.
How to fix it
The fix is to assign at least one meaningful policy initiative at the subscription scope. The best starting point is the Microsoft Cloud Security Benchmark (formerly the Azure Security Benchmark), a broad initiative that audits dozens of security controls in audit-only mode, so it reports without blocking anything.
Option 1: Azure portal
- Go to Policy in the Azure portal.
- Select Assignments in the left menu, then Assign initiative.
- Set the Scope to your subscription.
- For Initiative definition, search for and select Microsoft cloud security benchmark.
- Leave the effect parameters at their defaults (mostly audit) for a first pass.
- Review and select Create.
Within a few minutes you will see a compliance score appear and a list of resources evaluated against the benchmark.
Option 2: Azure CLI
First find the built-in initiative definition ID, then assign it to your subscription.
# Find the Microsoft Cloud Security Benchmark initiative
az policy set-definition list \
--query "[?displayName=='Microsoft cloud security benchmark'].{name:name, id:id}" \
-o table
# Assign it at the subscription scope (audit mode by default)
az policy assignment create \
--name "mcsb-baseline" \
--display-name "Microsoft Cloud Security Benchmark" \
--policy-set-definition "1f3afdf9-d0c9-4c3d-847f-89da613e70a8" \
--scope "/subscriptions/$(az account show --query id -o tsv)"
The GUID 1f3afdf9-d0c9-4c3d-847f-89da613e70a8 is the stable built-in ID for the Microsoft Cloud Security Benchmark, so you can reference it directly.
Option 3: A targeted single policy
If a full initiative is too much for a first step, start with one high-value deny policy. This one blocks creation of storage accounts that allow public blob access.
az policy assignment create \
--name "deny-public-blob" \
--display-name "Deny public blob access on storage accounts" \
--policy "4fa4b6c0-31ca-4c0d-b10d-24b96f62a751" \
--scope "/subscriptions/$(az account show --query id -o tsv)" \
--params '{"effect":{"value":"Deny"}}'
Danger: Assigning a deny policy takes effect immediately on new and updated resources. If you deny a configuration that existing pipelines depend on, deployments will start failing. Always assign new initiatives in audit mode first, review the compliance results, then switch specific controls to deny once you understand the blast radius.
How to assign with Infrastructure as Code
Clicking through the portal does not scale across many subscriptions. Define your assignments as code so they are versioned, reviewed, and reproducible.
Bicep
targetScope = 'subscription'
resource mcsbAssignment 'Microsoft.Authorization/policyAssignments@2024-04-01' = {
name: 'mcsb-baseline'
properties: {
displayName: 'Microsoft Cloud Security Benchmark'
policyDefinitionId: '/providers/Microsoft.Authorization/policySetDefinitions/1f3afdf9-d0c9-4c3d-847f-89da613e70a8'
enforcementMode: 'Default'
}
}
Terraform
data "azurerm_subscription" "current" {}
resource "azurerm_subscription_policy_assignment" "mcsb" {
name = "mcsb-baseline"
display_name = "Microsoft Cloud Security Benchmark"
subscription_id = data.azurerm_subscription.current.id
policy_definition_id = "/providers/Microsoft.Authorization/policySetDefinitions/1f3afdf9-d0c9-4c3d-847f-89da613e70a8"
}
Tip: Assign baseline initiatives at the management group scope instead of per subscription. A single assignment at the management group root then applies to every subscription beneath it, including ones created in the future, so new subscriptions are never born without guardrails.
How to prevent it from happening again
The durable fix is structural: make policy assignment part of how subscriptions are provisioned, not something a human remembers to do afterward.
Assign at the management group level
Build a management group hierarchy that mirrors your organization, then assign your security baseline at or near the root. Every subscription inherits the assignment automatically. This is the single most effective control, because it removes the per-subscription gap entirely.
Use Azure Landing Zones
The Azure Landing Zone reference architecture ships with a curated set of policy assignments baked into its management group structure. If you provision subscriptions through a landing zone vending process, governance comes attached by default.
Gate it in CI/CD
If your subscriptions and their assignments live in IaC, add a pipeline check that fails when a subscription has no assignment defined. A simple guard with the CLI:
#!/usr/bin/env bash
set -euo pipefail
SUB_ID=$(az account show --query id -o tsv)
COUNT=$(az policy assignment list \
--scope "/subscriptions/${SUB_ID}" \
--query "length(@)" -o tsv)
if [ "$COUNT" -eq 0 ]; then
echo "FAIL: subscription ${SUB_ID} has no policy assignments"
exit 1
fi
echo "OK: ${COUNT} policy assignment(s) found"
Wire this into a scheduled pipeline so drift is caught even when changes happen outside your IaC.
Tip: Lensix runs policy_noassignment continuously across your subscriptions, so you do not have to build the detection yourself. Use it as the safety net that catches subscriptions created or modified outside your normal provisioning path.
Best practices
- Start in audit mode. Assign broad initiatives with audit effects first to understand your current state before flipping anything to deny.
- Layer your scopes. Apply organization-wide baselines at the management group level and add subscription-specific or resource-group-specific policies where workloads need them.
- Pair audit with remediation. Use
deployIfNotExistspolicies to auto-deploy diagnostic settings, encryption, and monitoring agents instead of chasing them manually. - Map to a framework. Assign a recognized initiative like the Microsoft Cloud Security Benchmark or a CIS Azure benchmark so your compliance dashboard produces evidence auditors accept.
- Keep assignments in version control. Manage policy as code so changes are reviewed, and so a deleted assignment shows up in a diff rather than silently disappearing.
- Review exemptions. When you grant a policy exemption, set an expiration date and document the reason so temporary exceptions do not become permanent holes.
An empty policy surface is one of the quietest risks in an Azure tenant. It does not break anything, raise an alert, or cost money, which is exactly why it lingers. Assigning a single baseline initiative turns the lights on, and pushing that assignment up to the management group level makes sure they stay on for every subscription you create from here forward.

