Expert agent for Microsoft Defender EASM. Covers external attack surface discovery, inventory management, Azure integration, risk prioritization, Defender for Cloud integration, and dashboard configuration. WHEN: \"Defender EASM\", \"Microsoft EASM\", \"Defender External Attack Surface\", \"Azure EASM\", \"Microsoft attack surface management\".
Scanned 9/24/2026
npx -y skills add chrishuffman5/domain-expert --skill defender-easm --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Defender Easm?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/chrishuffman5-defender-easm)More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.
---
name: defender-easm
description: "Expert agent for Microsoft Defender EASM. Covers external attack surface discovery, inventory management, Azure integration, risk prioritization, Defender for Cloud integration, and dashboard configuration. WHEN: \"Defender EASM\", \"Microsoft EASM\", \"Defender External Attack Surface\", \"Azure EASM\", \"Microsoft attack surface management\"."
license: MIT
---
# Microsoft Defender EASM
This skill covers Microsoft Defender External Attack Surface Management (Defender EASM). It has expertise in external asset discovery, inventory management, risk scoring, integration with Microsoft Defender for Cloud, Microsoft Sentinel, and Azure-native workflows for managing internet-exposed assets.
## How to Approach Tasks
1. **Classify** the request:
- **Onboarding / setup** -- Resource creation, seed configuration, discovery
- **Inventory management** -- Asset labeling, filtering, management states
- **Risk analysis** -- Prioritizing exposures, CVE findings, SSL issues
- **Azure integration** -- Defender for Cloud, Sentinel, Microsoft 365 Defender
- **Reporting / dashboards** -- Built-in dashboards, custom reports, API exports
2. **Apply Microsoft ecosystem context** -- Defender EASM's key advantage is deep Azure integration. Organizations in the Microsoft security ecosystem (Sentinel, Defender for Cloud, MDE) get correlated external + internal exposure context.
## Product Overview
**Microsoft Defender EASM:** Azure-native external attack surface management service.
**Key characteristics:**
- Azure resource (deployed in Azure subscription, specific region)
- Priced per asset (IP/domain asset count, not per user)
- Deep integration with Azure: Defender for Cloud, Sentinel, Microsoft 365 Defender
- Internet-wide scanning using Microsoft's global internet scan infrastructure
- Free trial available for initial discovery assessment
**When Defender EASM fits best:**
- Organizations already invested in Microsoft security stack (Sentinel, Defender for Cloud, MDE)
- Azure-native preference (Azure portal, Azure Policy, ARM deployment)
- Budget-conscious (competitive pricing vs. Xpanse/CrowdStrike alternatives)
**Limitations vs. specialized EASM tools:**
- Less mature than Xpanse or CrowdStrike Falcon Surface (launched 2022)
- Automation/SOAR integration requires more custom work
- Fewer pre-built integrations with non-Microsoft tools
## Deployment
### Creating a Defender EASM Resource
**Azure Portal:**
1. Search "Defender EASM" in Azure Marketplace
2. Create resource:
- Subscription, Resource Group
- Region (choose region near your operations)
- Name: `easm-companyname-prod`
3. Resource deploys in ~2 minutes
**Azure CLI:**
```bash
# Register provider if needed
az provider register --namespace Microsoft.Easm
# Create Defender EASM workspace
az easm workspace create \
--workspace-name "easm-prod" \
--resource-group "rg-security" \
--location "eastus"
```
**Terraform:**
```hcl
resource "azurerm_easm_workspace" "main" {
name = "easm-prod"
resource_group_name = azurerm_resource_group.security.name
location = "East US"
}
```
### Adding Discovery Seeds
After creating the workspace, add discovery seeds:
**Via Azure Portal:**
1. Open Defender EASM workspace
2. Discovery > Discovery Groups > Create Discovery Group
3. Add seeds:
- **Domains:** company.com, company.net
- **IP Blocks:** 198.51.100.0/24
- **ASN:** AS12345
- **Hosts:** specific hostnames
- **Email contacts:** security@company.com (finds certs with this email)
- **WHOIS organizations:** legal entity names
4. Set discovery frequency: Weekly (default) or custom schedule
5. Run discovery
**Via API (REST):**
```bash
# Create discovery group via REST API
EASM_BASE="https://management.azure.com/subscriptions/{sub}/resourceGroups/{rg}/\
providers/Microsoft.Easm/workspaces/{workspace}"
curl -X PUT "${EASM_BASE}/discoveryGroups/main?api-version=2023-04-01-preview" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"properties": {
"seeds": [
{"kind": "domain", "name": "company.com"},
{"kind": "ipBlock", "name": "198.51.100.0/24"}
],
"frequencyMilliseconds": 604800000
}
}'
```
## Asset Inventory Management
### Asset States
Every discovered asset can be in one of these states:
| State | Meaning |
|---|---|
| **Candidate** | Discovered but not confirmed as org's asset |
| **Confirmed Inventory** | Accepted as belonging to your org |
| **Dependencies** | Third-party assets your confirmed assets depend on |
| **Monitor Only** | Watching but not managing (subsidiaries, partners) |
| **Requires Investigation** | Flagged for review |
| **Dismissed** | Not your asset, removed from scope |
| **Archived** | Was your asset, now decommissioned |
**Workflow:** Discovered assets start as "Candidate" → Review → Mark as "Confirmed Inventory" or "Dismissed"
### Asset Labels
Apply custom labels for organization and filtering:
- **Business unit:** `finance`, `engineering`, `marketing`
- **Environment:** `production`, `staging`, `development`
- **Risk tier:** `tier-1`, `tier-2`
- **Compliance scope:** `pci-scope`, `hipaa`
- **Geography:** `us`, `eu`, `apac`
```bash
# Apply label via API
curl -X PATCH "${EASM_BASE}/assets/domains/company.com?api-version=2023-04-01-preview" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{"labels": {"environment": "production", "tier": "1"}}'
```
## Risk Analysis
### Defender EASM Attack Surface Summary Dashboard
Built-in dashboard showing:
- **Exposed services by category:** Web, email, VPN, developer portals, remote access
- **SSL/TLS issues:** Expired, expiring in < 30 days, weak cipher suites, self-signed
- **Open vulnerabilities:** CVEs on detected software versions
- **Observations:** Policy violations (open RDP, exposed admin panels)
### Insight Cards
Insight Cards are pre-built risk findings across categories:
**Observation categories:**
- RDP accessible on internet
- SSH accessible on internet (open to all IPs)
- FTP services exposed
- Databases exposed (MySQL, MSSQL, MongoDB, Postgres, Redis)
- Kubernetes API publicly accessible
- Expired SSL certificates
- CVEs on web server versions
- Outdated software frameworks (PHPMyAdmin, old Tomcat, etc.)
- Admin interfaces accessible (phpAdmin, Jenkins, GitLab without auth)
### CVE Integration
Defender EASM maps detected software versions to CVEs:
- Shows CVE IDs, CVSS scores, and affected technology
- Filtered by: severity (Critical/High/Medium/Low), CISA KEV status
- Example: "Apache 2.4.49 detected on ip.x.x.x -- CVE-2021-41773 (CVSS 9.8, KEV)"
## Azure Integration
### Defender for Cloud Integration
Export Defender EASM inventory to Defender for Cloud:
1. In Defender for Cloud: Environment Settings > External Attack Surface
2. Connect EASM workspace
3. EASM-discovered assets appear as external inventory in Defender for Cloud
4. Correlate EASM findings with Defender for Cloud CSPM recommendations
**Use case:** "This internet-exposed Azure VM (found by EASM) has 3 critical Defender for Cloud recommendations (found by MDfC CSPM)" -- unified in one view.
### Microsoft Sentinel Integration
Send EASM findings to Sentinel for correlation and detection:
**Enable Sentinel data connector:**
1. Sentinel > Data Connectors > Microsoft Defender EASM
2. Connect to EASM workspace
3. EASM findings flow into Sentinel as `EasmAsset_CL` and `EasmInsight_CL` tables
**KQL queries in Sentinel:**
```kql
// EASM: New critical insights (last 7 days)
EasmInsight_CL
| where TimeGenerated > ago(7d)
| where severity_s in ("High", "Critical")
| project TimeGenerated, assetName_s, insightName_s, severity_s, state_s
| sort by TimeGenerated desc
// EASM: Expired SSL certificates
EasmInsight_CL
| where insightName_s contains "SSL" and insightName_s contains "expired"
| where state_s == "Active"
| project assetName_s, insightName_s, TimeGenerated
// Correlate EASM external exposure with MDE alerts on same IP
let easm_ips = EasmAsset_CL
| where assetType_s == "IP Address"
| where state_s == "Confirmed"
| project ip = name_s;
DeviceAlerts
| where LocalIP in (easm_ips) or RemoteIP in (easm_ips)
| project Timestamp, DeviceName, AlertName, Severity, LocalIP, RemoteIP
```
### Logic Apps / Power Automate
Automate EASM workflows with Azure Logic Apps:
**Example: New critical exposure → ServiceNow ticket**
```
Trigger: Recurrence (every 24 hours)
Action 1: HTTP GET - Defender EASM API (get new Critical insights since yesterday)
Action 2: For each insight with severity=Critical:
Action 2a: ServiceNow - Create Incident
Short Description: "EASM Critical Exposure: {insightName}"
Description: "Asset: {assetName}\nInsight: {insightDetails}\nURL: {easm_link}"
Priority: 2 (High)
Assignment Group: Security Operations
```
## API Reference
**Authentication:** Azure AD token (OAuth 2.0, scope: `https://easm.defender.microsoft.com/.default`)
**Key endpoints:**
```
GET /assets # List assets with filters
GET /assets/{assetId} # Get asset details
PATCH /assets/{assetId} # Update asset state/labels
GET /insights # Get risk insights/findings
POST /discoveryGroups # Create discovery group
GET /discoveryGroups/{id}/runs # Discovery run history
GET /summaries/asset # Asset count summary
GET /summaries/insight # Insight count by severity/type
```
**Python example:**
```python
import requests
from azure.identity import DefaultAzureCredential
# Get token
credential = DefaultAzureCredential()
token = credential.get_token("https://easm.defender.microsoft.com/.default")
EASM_BASE = (
"https://eastus.easm.defender.microsoft.com/subscriptions/{sub_id}"
"/resourceGroups/{rg}/workspaces/{workspace_name}"
)
headers = {"Authorization": f"Bearer {token.token}"}
# Get all confirmed inventory assets
response = requests.get(
f"{EASM_BASE}/assets",
headers=headers,
params={
"filter": "state eq 'confirmed'",
"$top": 100,
"api-version": "2023-04-01-preview"
}
)
for asset in response.json()["value"]:
print(f"{asset['kind']}: {asset['name']} - State: {asset['state']}")
```
## Pricing
Defender EASM pricing (as of 2024):
- First 1,000 billable assets: Free (trial/evaluation period)
- Per billable asset per month: Pay-as-you-go pricing
- Billable assets = confirmed inventory assets (candidates and dismissed don't count)
- Check Azure pricing calculator for current rates
**Cost control:**
- Regularly review and "Dismiss" assets that aren't yours
- Archive decommissioned assets rather than leaving as "Confirmed"
- Set budget alerts in Azure Cost Management
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!