Open-Source Azure Entra ID Security Scanner: Automated Threat Discovery with Custom Extensibility
Azure Entra Security ScannerArtificial Intelligence

Open-Source Azure Entra ID Security Scanner: Automated Threat Discovery with Custom Extensibility

## The Problem Every CISO Knows Your Azure Entra ID tenant is the front door to your entire cloud estate. Behind that door: hundreds of app registrations with over-permissioned secrets, service principals with stale credentials, conditional access policies with gaps you don't know about, and attack paths that chain these misconfigurations into real breaches. Microsoft provides tools. They're scattered across Defender, Entra admin center, Azure Portal, and Graph API queries you run manually. None of them give you a unified, scored, actionable view of your Entra security posture — and none of them let your team extend the scanning with organization-specific checks.

JP Admin User
March 10, 2026
6 min read
45 views

We built one that does.

What It Does

The Azure Entra Security Scanner is a self-hosted, open-source tool that performs automated security assessments of your Azure Entra ID tenants. In under 5 minutes, it scans your entire tenant and surfaces findings across 13 security domains — then scores everything so you know what to fix first.

What Gets Scanned

The scanner runs a 10-phase pipeline that covers:

DomainWhat's Analyzed
App RegistrationsCredentials, secret expiry, permission scope, owner chains
Service PrincipalsEnterprise apps, PIM eligibility, stale access
Conditional AccessPolicy gaps, exclusion risks, grant control strength
Attack PathsLateral movement chains across apps, principals, and permissions
Virtual MachinesNetwork exposure, disk encryption, security extensions
Key VaultsAccess policies, secret management, network rules
Function AppsConfiguration security, trigger exposure, runtime settings
Identity ProtectionRisky users, risky service principals
Security AlertsActive Microsoft Defender incidents
Advanced HuntingCustom KQL query results from Microsoft 365 Defender
Secure ScoreMicrosoft Secure Score metrics and control profiles

Every finding gets a severity rating. Every resource gets a risk score. The dashboard gives you sortable, filterable tables with drill-down into each finding — not a PDF you forward to someone else.

The Dashboard

A Next.js dashboard renders scan results in real-time with:

  • Risk-scored overview per tenant with trend visualization
  • 13 dedicated views — one per security domain — with sortable data tables
  • Attack path visualization showing how misconfigurations chain together
  • Methodology page explaining how scores are calculated (transparency builds trust)

Everything runs in Docker. No SaaS dependency, no data leaving your network.

The Custom Scripts System: Your Security Playbook, Codified

Here's where it gets interesting for teams with mature security practices.

Every organization has specific checks that generic scanners miss. Maybe you need to find users without hardware FIDO2 keys. Maybe you audit app registrations that bypass your naming convention. Maybe you check for service principals created outside your provisioning pipeline.

The Custom Scanner Plugin System lets your team write Python scripts that:

  1. Run with pre-authenticated Microsoft Graph and ARM clients — no credential handling
  2. Define their own dashboard tab — with typed columns, icons, and descriptions
  3. Execute safely — read-only by design, 60-second timeout, subprocess isolation
  4. Test before deploying — built-in test-run panel with tenant selection

How It Works (For Engineers)

You write a Python class that inherits from CustomScanner:

python
from scanner.custom import Column, ColumnType, CustomScanner, ScanContext

class StaleAppSecrets(CustomScanner):
    name = "Stale Secrets"
    description = "App registrations with secrets expiring within 30 days"
    icon = "key-round"

    columns = [
        Column(key="app_name", label="Application", col_type=ColumnType.TEXT),
        Column(key="secret_name", label="Secret", col_type=ColumnType.TEXT),
        Column(key="expires", label="Expiry Date", col_type=ColumnType.DATE),
        Column(key="severity", label="Risk", col_type=ColumnType.SEVERITY),
    ]

    async def scan(self, context: ScanContext) -> list[dict]:
        apps = await context.graph.applications.get()
        # Your logic here — return rows matching column keys
        return rows

The framework handles everything else: authentication, execution, error isolation, result storage, and dashboard rendering. Your script becomes a new tab in the sidebar — automatically.

How It Works (For Decision Makers)

Your security engineers open a browser, click "Custom Scripts," write a check, test it against a real tenant, and activate it. Next scan, it runs alongside the built-in checks. Results show up in the same dashboard as everything else — same sortable tables, same severity badges, same export capabilities.

No deployment pipeline. No code review bottleneck for security checks. No vendor ticket to add a new scanning rule. Your team owns their security playbook.

Architecture: Why These Choices

Self-Hosted, Not SaaS

Your Entra ID data includes app credentials, permission grants, conditional access rules, and attack path maps. This is a blueprint for compromising your tenant. It never leaves your network.

The entire stack runs in Docker Desktop or any container orchestrator:

ComponentTechnologyRole
ScannerPython + Microsoft Graph SDKExecutes security assessments
BackendNode.js + Azure FunctionsAPI layer + Cosmos DB storage
DashboardNext.js + TanStack TableReal-time security visualization
SidecarFastAPIOn-demand script test execution
StorageCosmos DB emulator + AzuriteZero-cost local persistence

Why Python for Scanning, TypeScript for the Stack?

Python is the lingua franca of security tooling. Your team already writes Python. The Microsoft Graph SDK for Python has first-class async support. Making them learn TypeScript to write security checks would kill adoption.

The dashboard and backend are TypeScript because Next.js gives us server-side rendering (fast initial loads with large datasets), and the Azure Functions runtime gives us a clean API layer with built-in Cosmos DB bindings.

Why Subprocess Isolation for Custom Scripts?

Every custom script runs in a fresh Python subprocess. Not imported via importlib. Not executed in the same process. This is deliberate:

  • No memory leaks — each script gets a clean interpreter
  • No module pollution — one script's imports can't affect another
  • Hard timeout enforcementasyncio.wait_for() kills the subprocess cleanly
  • Crash containment — a segfault in a custom script doesn't take down the scanner

The trade-off is ~2 seconds of subprocess startup overhead per script. For security tooling that runs on a schedule, that's noise.

Deployment: 5 Minutes to First Scan

Prerequisites: Docker Desktop, an Azure AD App Registration with Directory.Read.All (application permission).

bash
git clone <repo>
cp .env.example .env
# Add TENANT_ID, CLIENT_ID, CLIENT_SECRET

docker compose up -d             # Start the stack
docker compose run --rm scanner  # Run first scan

Open http://localhost:3000. Your tenant's security posture is on screen.

What Permissions Are Needed?

The scanner uses read-only application permissions:

PermissionWhy
Directory.Read.AllApp registrations, service principals, users
Policy.Read.AllConditional access policies
SecurityEvents.Read.AllSecurity alerts, risky users
ThreatHunting.Read.AllAdvanced hunting queries

No write permissions. No admin consent for delegated access. The app registration is a read-only observer of your tenant.

What's Next

This tool is built for teams that take Entra ID security seriously but are tired of cobbling together PowerShell scripts, manual Graph API queries, and spreadsheet audits.

For security engineers: Write your organizational checks once, run them on every scan, see results in a real dashboard.

For security leaders: Get a single-pane view of your Entra security posture that your team can extend without vendor dependencies.

For compliance teams: Every finding is scored, timestamped, and stored locally — ready for audit evidence.

The scanner is open-source. Deploy it today, run your first scan, and see what your tenant is actually exposing.


Azure Entra Security Scanner v0.0.19 — Self-hosted, extensible, read-only by design.

Share this post

About JP Admin User

AI and software development enthusiast

Gallery

Related Posts