Azure SQL databases without Microsoft Defender for SQL threat detection
What does ZopNight detect here?
Microsoft Defender for SQL is off when ZopNight's discoverer reads threat_detection_enabled as "false" from the server's security-alert policy. SQL injection attempts, brute-force logins, and unusual access patterns then go undetected. RC-1332 rates the gap high severity, fires only on that explicit "false", and abstains when the metadata is absent.
Signal and threshold
| Field | Value |
|---|---|
| Rule IDs | RC-1332 |
| Category | compliance |
| Severity | high |
| Metric | none — pure configuration read |
| Source | sql_threat_detection.go |
Where it applies
Attacks that succeed quietly
A database without Advanced Threat Protection does not fail differently under attack. It fails silently. SQL injection probing, brute-force login attempts, logins from anomalous locations, and unusual data-exfiltration query patterns all look like ordinary traffic unless something is classifying them. Defender for SQL is Azure’s classifier for exactly these patterns, and with it disabled the first sign of a compromised database is often the data showing up somewhere it shouldn’t. Auditing (a separate rule, RC-1331) records what happened; threat detection is the layer that tells you while it is happening.
Where the evidence comes from
The Azure discoverer derives the state from the SQL server’s security-alert policy and
stamps threat_detection_enabled into resource metadata. RC-1332 fires only when that value
is the explicit string "false". Absent metadata means the rule abstains. It never fires
on missing evidence. The original version of this rule read a threat_detection tag, which
was both the wrong field and the wrong key; no producer wrote it, so the rule was dead on
real data until it was re-pointed at the policy-derived metadata. Reading the policy needs
only the built-in Reader role.
A server policy surfaced per database
Defender for SQL is typically enabled at the server (or subscription) scope and inherited, which is why the discoverer reads the server’s security-alert policy. Enabling it at the server covers every database on that server; enabling Defender at subscription scope covers every server. If you are going to act on one finding, act at the widest scope you can. The per-database view is just where the gap becomes visible.
Reproduce the check
az sql server advanced-threat-protection-setting show \ --resource-group <rg> --name <server> \ --query stateDisabled matches what the rule detected.
Before you enable it everywhere
Two honest caveats. First, Defender for SQL is a paid add-on billed per server (worth it for production data, but a real line item across a large estate), which is why this finding is compliance-categorized with a $0 saving rather than pretending enablement is free. Second, alerts are only useful if they reach someone: configure the alert email recipients or Defender’s integration with your incident channel when you turn it on, or you have replaced silent failure with unread notifications.