Skip to content

Microsoft Defender for Cloud -- Findings Management Process

Overview

This document defines how the eshars team triages, tracks, and resolves Microsoft Defender for Cloud security recommendations across our Azure environment.

All findings are tracked in the Jira DEVOPS project under severity-based Epics. Severity tiers match Defender’s recommendation severity directly (High/Medium/Low).

Jira Epic Structure

EpicKeyPrioritySLAUse For
Defender - HighDEVOPS-82High1 weekMatches Defender High severity recommendations
Defender - MediumDEVOPS-83Medium2 weeksMatches Defender Medium severity recommendations
Defender - LowDEVOPS-84Low1-2 sprintsMatches Defender Low severity recommendations
Defender - Non-IssueDEVOPS-85LowestDocument & closeFalse positive, not applicable, compensating control exists
Defender - Won’t Do (Pending Approval)DEVOPS-86LowAwaiting approvalTeam lead must approve before closing

Note: Defender recommendations use 3 severity levels (High/Medium/Low). The “Critical” category shown in the Defender portal is a risk-based aggregation that considers attack paths, internet exposure, and resource context — it is NOT a per-recommendation severity. We capture risk-based status using labels (see below).

Label Taxonomy

Required Labels

LabelWhen to Apply
DefenderEvery Defender-sourced finding (required)
defender-highIssue under DEVOPS-82 (High)
defender-mediumIssue under DEVOPS-83 (Medium)
defender-lowIssue under DEVOPS-84 (Low)
defender-nonissueIssue under DEVOPS-85
defender-wontdoIssue under DEVOPS-86

Environment Labels

LabelWhen to Apply
env-prodFinding affects at least one production resource
env-nonprodFinding affects at least one non-production resource

Issues affecting both environments get both labels.

Classification rules:

  • prod: resource name/group contains prod, prodwest, tmhp, sftp, ssrs16-prod, rns-prod
  • non-prod: resource name/group contains nonprod, dev, uat, qa, training, regression, test, poc, interview
  • ambiguous: flag for team lead confirmation, default to prod (safer)

Risk-Based Labels (Optional)

LabelWhen to Apply
risk-criticalFinding appears in Defender’s Critical risk-based view (portal)
risk-highFinding appears in Defender’s High risk-based view
attack-pathFinding has associated attack path alerts

These labels capture the Defender portal’s risk-based aggregation, which considers factors beyond recommendation severity (attack paths, internet exposure, lateral movement potential). Review and update these during monthly intake.

Jira Conventions

  • Label (required): Defender + severity label + at least one env label
  • Priority: Must match the severity Epic (High/Medium/Low/Lowest)
  • Epic Link (customfield_10007): Must point to the matching severity Epic
  • Issue Type: Task (under the appropriate Epic)

Severity Assignment

Severity comes directly from Defender’s recommendation severity (High/Medium/Low). We no longer apply custom severity assessments.

  1. Pull the finding from az security assessment-metadata list to get the recommendation severity
  2. Assign to the matching Epic
  3. If severity is “Unknown” (e.g., MDVM secrets scanner findings), default to Medium

When to Override Defender Severity

Override only with team lead approval and documented justification:

  • Upgrade: Finding has known active exploit or direct compliance impact
  • Downgrade: Compensating control fully mitigates the risk (move to Non-Issue instead)

Intake: Pulling New Findings

Run these commands monthly (at minimum) to check for new Defender recommendations:

Terminal window
# Ensure correct subscription
az account set --subscription 9639039c-86c6-4859-b014-d28688863cd5
# Pull assessment metadata (contains severity)
az security assessment-metadata list -o json > security/metadata-$(date +%Y%m%d).json
# Pull unhealthy assessments (contains affected resources)
az security assessment list \
--query "[?status.code=='Unhealthy']" \
-o json > security/assessments-$(date +%Y%m%d).json
# Join and summarize using parse script
python security/parse_defender.py \
security/metadata-$(date +%Y%m%d).json \
security/assessments-$(date +%Y%m%d).json \
> security/findings-$(date +%Y%m%d).json

Cross-reference findings against the register (defender-register.md) and existing Jira tickets (JQL: project = DEVOPS AND labels = Defender). Create new tickets for any untracked findings.

Triage Workflow

  1. New finding arrives — Create Jira Task in DEVOPS project
    • Set label: Defender + severity label (e.g., defender-high) + env labels
    • Set priority to match severity Epic
    • Set Epic Link (customfield_10007) to the matching severity Epic
    • Description: Include Defender recommendation name, affected resources, resource count
  2. Initial assessment (within 3 business days of discovery)
    • Engineer reviews the finding and affected resources
    • Confirms Defender severity is appropriate (or proposes override with justification)
    • Classifies resources as prod/non-prod, adds env labels
    • Checks Defender portal for risk-based status, adds risk labels if applicable
  3. Categorization review
    • Team lead confirms or adjusts severity
    • If “Non-Issue” or “Won’t Do”, see approval process below

Wave Prioritization

Remediation is prioritized by severity and environment:

WaveScopeJQLTimeline
1High + prodlabels = Defender AND labels = env-prod AND parent = DEVOPS-82 AND status != DoneImmediate
2High + non-prod, Medium + prodCombined queryNext sprint
3Medium + non-prodlabels = Defender AND labels = env-nonprod AND parent = DEVOPS-83 AND status != DoneFollowing sprint
4Low + prodlabels = Defender AND labels = env-prod AND parent = DEVOPS-84 AND status != DoneBacklog
5Low + non-prodlabels = Defender AND labels = env-nonprod AND parent = DEVOPS-84 AND status != DoneBacklog

Items with risk-critical or attack-path labels should be prioritized within their wave.

”Won’t Do” Approval Process

When a finding is evaluated and the recommendation should NOT be implemented:

  1. Engineer adds comment to the Jira ticket with:
    • Justification: Why this will not be implemented
    • Compensating controls: What mitigations exist instead
    • Risk acceptance: What residual risk remains
  2. Engineer moves ticket to the “Defender - Won’t Do (Pending Approval)” Epic (DEVOPS-86)
  3. Team lead must approve by adding a comment with [APPROVED - Won't Do]
  4. Only after approval can the ticket be moved to Done
  5. If team lead disagrees, they reassign back with revised instructions

IMPORTANT: No finding may be marked as “Won’t Do” without team lead approval.

Release Notes

When Defender findings are resolved, update the release notes:

  1. Use the template at security/release-notes/TEMPLATE.md
  2. Create a new file: security/release-notes/YYYY-MM-DD-batch-N.md
  3. Document each resolved finding following the template format
  4. Include: What happened, Solution steps, QA considerations, Deployment considerations

Ongoing Cadence

FrequencyActivity
ImmediatelyHigh findings affecting prod go into current sprint
MonthlyPull latest Defender findings, create tickets for new items, update risk labels
Sprint planningInclude Defender items per wave prioritization
Sprint closeGenerate release notes for resolved Defender items
QuarterlyFull review of all open Defender items with team lead

Quick JQL Reference

FilterJQL
All Defender itemsproject = DEVOPS AND labels = Defender ORDER BY priority DESC
Open itemsproject = DEVOPS AND labels = Defender AND status != Done ORDER BY priority DESC
Highproject = DEVOPS AND labels = Defender AND parent = DEVOPS-82
Mediumproject = DEVOPS AND labels = Defender AND parent = DEVOPS-83
Lowproject = DEVOPS AND labels = Defender AND parent = DEVOPS-84
Prod + Highproject = DEVOPS AND labels in (Defender, env-prod) AND parent = DEVOPS-82 AND status != Done
Non-prod onlyproject = DEVOPS AND labels = Defender AND labels = env-nonprod AND labels not in (env-prod) AND status != Done
Risk Criticalproject = DEVOPS AND labels in (Defender, risk-critical) AND status != Done
Attack Pathproject = DEVOPS AND labels in (Defender, attack-path) AND status != Done