Third-Party Application Vulnerabilities
A single Azure Monitor workbook with two domains β Entra ID Applications queried through Microsoft Graph, and Software Vulnerabilities reported by Microsoft Defender via Azure Resource Graph. Deployable with Bicep, with a matching Postman collection and a Pester test suite.
What this repo is — and isn't
Important context before you begin: the tool reports two different kinds of data, and only one of them is “vulnerabilities.”
β What this repo is
- A read-only Azure Monitor workbook that reports two data sets behind one domain selector.
- Software domain: genuine third-party CVE findings from Microsoft Defender Vulnerability Management, via Azure Resource Graph, scoped to non-Microsoft vendors.
- Entra domain: an inventory & posture view of app registrations, enterprise apps, credentials, delegated consents, and app-only Microsoft Graph permissions.
- Deployable as code (Bicep), with a matching Postman collection and a 76-test suite (including Graph transform contract tests).
- Least-privilege and low blast radius: delegated read in the workbook; no data is written or exported.
β What this repo isn't
- Not a vulnerability scanner for Entra/Graph — Microsoft Graph does not expose app CVEs; the Entra tabs are inventory and configuration, not findings.
- Not a vulnerability-management product: no risk scoring, prioritization, remediation, ticketing, alerting, or tracking.
- Not a complete permissions audit — the app-permissions tab covers Microsoft Graph only, not SharePoint, Exchange, or Key Vault.
- Not turnkey for every tenant: recommendations need Entra ID P1/P2 (beta endpoint) and CVEs need Defender for Servers P2 / MDVM onboarding.
- Not a credential-expiry monitor — secret/certificate end-dates are listed, but not flagged as expired or expiring.
Two domains, one selector
Switch between the two domains using the top-level domain selector inside the workbook.
πͺͺ Entra ID Applications Microsoft Graph
App registrations and enterprise applications: recommendations, inventory, credentials, delegated consents, and app-only Microsoft Graph permissions.
π Software Vulnerabilities Defender / ARG
Software CVEs reported by Microsoft Defender Vulnerability Management (MDVM), queried through Azure Resource Graph and filtered to non-Microsoft vendors.
Repository contents
Everything needed to deploy, query, and test the workbook.
| File | Purpose |
|---|---|
workbook/third-party-vulnerabilities.workbook.json | The workbook definition. |
workbook/deploy.bicep | Deploys the workbook from the JSON file. |
postman/β¦postman_collection.json | Postman collection calling the same Microsoft Graph endpoints as the Entra ID tabs, plus a Defender advanced hunting (KQL) request. |
postman/β¦postman_environment.json | Postman environment template for the collection. |
tests/Repo.Tests.ps1 | Pester tests for the workbook, Bicep, and Postman artifacts. |
tests/graph-transform.test.mjs | Data-contract tests evaluating the workbook's real Graph jsonpath column paths against fixtures. |
tests/postman/postman.test.mjs | Node behavioral harness executing the embedded Postman JavaScript with coverage. |
Deploy the workbook
Use Bicep, or import the JSON directly in the Azure portal.
Option A β Bicep
# Create a resource group, then deploy
az group create --name rg-security-workbooks --location westeurope
az deployment group create `
--resource-group rg-security-workbooks `
--template-file workbook/deploy.bicep
Outputs workbookResourceId and workbookName.
Option B β Portal import
Open the Advanced Editor
Azure Portal β Monitor β Workbooks β + New β Advanced Editor (</>).
Paste the JSON
Paste the contents of workbook/third-party-vulnerabilities.workbook.json.
Save
Apply β Done Editing β Save.
az login). Entra domain needs Microsoft Graph delegated read (Global Reader or Security Reader). The Entra recommendations tab requires Entra ID P1/P2. The Software domain needs Defender for Servers Plan 2 / MDVM and Reader on the selected subscriptions. Saving needs Monitoring Contributor or Workbook Contributor.Entra ID Applications
Each tab runs a Microsoft Graph query and renders the result as a table.
| Tab | Graph endpoint |
|---|---|
| Entra recommendations | GET /beta/directory/recommendations |
| Enterprise application inventory | GET /v1.0/servicePrincipals |
| Application credentials | GET /v1.0/applications |
| Delegated permission grants | GET /v1.0/oauth2PermissionGrants |
| Microsoft Graph app permissions | GET /v1.0/servicePrincipals(appId='00000003-β¦')/appRoleAssignedTo |
Software Vulnerabilities (Defender)
Set the Subscriptions, Severity, and Vendor filters, then select a tab.
| Tab | Content |
|---|---|
| CVE Findings | Each CVE finding with severity, CVSS, software, vendor, patchability, and resource. |
| Vulnerable Software | Software inventory aggregated by vendor/product with device counts. |
| Affected Devices | Devices with Critical/High counts and distinct CVE counts. |
| End-of-Support Software | Products reported as unsupported or approaching end of support. |
Data sources (Azure Resource Graph): microsoft.security/assessments/subassessments for CVE findings and microsoft.security/softwareinventories for inventory and end-of-support. Queries use coalesce(β¦) for property names that vary by plan and filter out vendors containing microsoft.
Microsoft Graph & Defender via Postman
Call the same five Graph endpoints from a client using app-only (client-credentials) auth, plus a sixth request that runs a KQL query against the Microsoft Defender for Endpoint advanced hunting API.
Setup
Register an app
Add a client secret and the Graph application permissions DirectoryRecommendations.Read.All, Application.Read.All, Directory.Read.All. For request 6, also add the WindowsDefenderATP permission AdvancedQuery.Read.All. Grant admin consent.
Import both files
Import the collection and environment from postman/.
Set variables
Set tenantId, clientId, and clientSecret in the environment.
Send a request
The pre-request script fetches and caches an app-only bearer token automatically.
Permission models
Workbook (delegated): runs as the signed-in user. A directory role such as Global Reader or Security Reader is enough β no app registration or secret.
Postman (application): runs as an app registration with app-only permissions and a client secret, not tied to a user, requiring admin consent.
Defender request (request 6): runs a KQL advanced hunting query against api.securitycenter.microsoft.com, authorized by the AdvancedQuery.Read.All Defender permission (not a Graph permission). A request-level pre-request script caches a separate token in defender_access_token; its response returns a Results array with no paging.
Pagination: responses return a value array; when more results exist an @odata.nextLink is stored in nextLink. Send the Next page request until it is no longer set.
Tests & coverage
Pester validates the artifacts; a Node harness executes the embedded Postman JavaScript with enforced coverage.
Run the suite
# From the repository root
Invoke-Pester -Path ./tests -Output Detailed
Requires PowerShell 7+, Pester 5+, Node.js, and Azure CLI (to compile the Bicep template).
What is covered
The behavioral harness runs the embedded Postman scripts against mocks at 100% line, ~90% branch, and 100% function coverage, enforced at a β₯80% threshold.