This check flags Azure subscriptions that have no activity log alert wired up for security policy changes. Without it, an attacker or careless admin can weaken your Azure Policy and Defender for Cloud settings without anyone noticing. Fix it by creating an activity log alert on the Microsoft.Authorization/policyAssignments and Microsoft.Security/policies operations that pushes to an action group.
Security policy is one of the quietest control planes in Azure. Most teams set up Azure Policy assignments and Microsoft Defender for Cloud settings once, then forget about them. That is exactly why changes to those policies are so dangerous. A single edit can turn off encryption enforcement, drop a deny rule, or disable a Defender plan across an entire subscription, and nobody finds out until an audit or an incident.
The Lensix check activitylog_nosecuritypolicy looks for an Azure Monitor activity log alert that fires when security policy changes happen. If no such alert exists in the subscription, the check fails.
What this check detects
Azure writes every control plane operation to the Activity Log, including changes to policy assignments and security configurations. This check verifies that at least one activity log alert rule is configured to watch for those security policy operations and notify someone when they occur.
Specifically, it cares about operations such as:
Microsoft.Authorization/policyAssignments/writeand/deleteMicrosoft.Authorization/policyDefinitions/writeand/deleteMicrosoft.Security/policies/writeMicrosoft.Security/pricings/write(Defender plan changes)
When the check fails, it means these events are still being recorded in the Activity Log, but no one is being told about them in real time. The data exists, the alarm does not.
Note: An activity log alert is different from a metric alert. Metric alerts watch numeric telemetry like CPU or request count. Activity log alerts watch control plane events, which is what makes them the right tool for tracking configuration changes.
Why it matters
Security policy changes are a favorite move for attackers who already have a foothold. Once an identity with sufficient rights is compromised, weakening the guardrails is often step one, because it makes everything after that easier and quieter.
Consider a realistic chain of events:
- An attacker phishes credentials for an account with Contributor or Owner on a subscription.
- They delete a policy assignment that enforced "deny public blob access" so they can later exfiltrate data through a public storage container.
- They downgrade Microsoft Defender for Cloud from Standard to Free to kill threat detection.
- They carry out the actual attack with most of your detection capability already switched off.
If you have no alert on security policy changes, steps two and three pass in silence. The change shows up in the Activity Log, but logs no one reads are not security controls. They are just storage.
There is a compliance dimension too. Frameworks like CIS Microsoft Azure Foundations Benchmark explicitly require an activity log alert for the creation, update, or deletion of security policies. Failing this check is a direct finding in a CIS or SOC 2 audit, not a nice-to-have.
Warning: Even well-meaning admins cause damage here. Someone cleaning up "unused" policy assignments in a shared subscription can quietly remove a control that protected three other teams. An alert turns that into a conversation instead of a surprise.
How to fix it
You need two things: an action group that defines who gets notified, and an activity log alert that watches the right operations and points at that action group.
Step 1: Create an action group
The action group decides where the notification goes. Email, SMS, webhook, or a ticketing integration all work.
az monitor action-group create \
--name "sec-policy-alerts" \
--resource-group "monitoring-rg" \
--short-name "secpolicy" \
--action email secops [email protected]
Step 2: Create the activity log alert
Now create an alert that fires on policy assignment writes. The category for these events is Administrative, and you scope it to the subscription.
az monitor activity-log alert create \
--name "alert-policy-assignment-change" \
--resource-group "monitoring-rg" \
--scope "/subscriptions/00000000-0000-0000-0000-000000000000" \
--condition category=Administrative and operationName=Microsoft.Authorization/policyAssignments/write \
--action-group "sec-policy-alerts" \
--description "Fires when an Azure Policy assignment is created or updated"
Repeat for the delete operation and for the Defender pricing change, since each operation name needs its own condition or its own alert rule:
az monitor activity-log alert create \
--name "alert-policy-assignment-delete" \
--resource-group "monitoring-rg" \
--scope "/subscriptions/00000000-0000-0000-0000-000000000000" \
--condition category=Administrative and operationName=Microsoft.Authorization/policyAssignments/delete \
--action-group "sec-policy-alerts" \
--description "Fires when an Azure Policy assignment is deleted"
az monitor activity-log alert create \
--name "alert-defender-pricing-change" \
--resource-group "monitoring-rg" \
--scope "/subscriptions/00000000-0000-0000-0000-000000000000" \
--condition category=Administrative and operationName=Microsoft.Security/pricings/write \
--action-group "sec-policy-alerts" \
--description "Fires when a Defender for Cloud plan is changed"
Tip: Operation names in activity log alerts do not support wildcards in a single condition the way you might hope. If you want broad coverage, create one alert per operation, or manage them as a set through IaC so the list stays consistent across subscriptions.
Through the Azure Portal
If you prefer the console:
- Go to Monitor then Alerts, and select Create then Alert rule.
- Set the scope to your subscription.
- Under Condition, choose Activity Log as the signal type and pick the operation, for example "Create policy assignment".
- Attach or create an action group with your notification target.
- Name the rule and create it.
Note: Activity log alerts are free in Azure Monitor. You only pay for the action group actions that have a cost, like SMS or voice calls. Email and webhook notifications carry no charge, so there is no good reason to skip this control.
How to prevent it from happening again
Creating one alert by hand solves the problem for one subscription today. The real goal is to make this alert exist everywhere, automatically, and stay there.
Deploy it as code with Bicep
Put the alert in your platform landing zone template so every new subscription gets it from day one.
resource policyChangeAlert 'Microsoft.Insights/activityLogAlerts@2020-10-01' = {
name: 'alert-policy-assignment-change'
location: 'Global'
properties: {
scopes: [
subscription().id
]
enabled: true
condition: {
allOf: [
{
field: 'category'
equals: 'Administrative'
}
{
field: 'operationName'
equals: 'Microsoft.Authorization/policyAssignments/write'
}
]
}
actions: {
actionGroups: [
{
actionGroupId: actionGroupResourceId
}
]
}
}
}
Enforce it with Azure Policy
Azure Policy can deploy this alert for you using a deployIfNotExists effect. That means any subscription missing the alert gets it created automatically through a remediation task, and drift is corrected without human effort.
Gate it in CI/CD
If you manage infrastructure through pipelines, add a check that fails the build when the alert resource is absent from a subscription's configuration. Lensix can also run activitylog_nosecuritypolicy on a schedule and flag any subscription where the alert has been removed, so detection does not depend on someone remembering to look.
Tip: Assign the alert and action group at the management group level through Azure Policy. New subscriptions inherit it automatically, which beats remembering to bootstrap monitoring every time the cloud estate grows.
Best practices
- Cover the full set of security operations. Do not stop at policy assignments. Include policy definition changes, Defender pricing changes, and security contact changes so the whole policy surface is watched.
- Route alerts somewhere people act on. An alert that lands in an unwatched inbox is no better than no alert. Send these to your SIEM, your on-call channel, or a ticket queue with an owner.
- Tie alerts to a runbook. When a policy change fires, responders should know the question to ask: was this change planned, who made it, and does it need to be reverted.
- Test the alert. Make a harmless policy assignment change in a non-production subscription and confirm the notification actually arrives. Untested alerting is wishful thinking.
- Pair detection with prevention. Lock critical policy assignments with Azure resource locks and restrict who holds policy write permissions. Detection tells you something broke; least privilege keeps it from breaking in the first place.
Danger: Do not solve a noisy alert by deleting the rule. If the alert fires too often, tune who gets notified or scope it more tightly, but keep the rule live. Removing it puts you straight back into the silent-failure state this check exists to prevent.
Security policy changes are low-frequency, high-impact events. They almost never happen by accident in a mature environment, which is precisely why every one of them deserves a notification. Wiring up this alert costs nothing and turns one of the quietest blind spots in Azure into a tripwire.

