BadZure builds a deliberately broken Entra ID tenant to practise on
BadZure automates the deployment of intentionally misconfigured Entra ID tenants and Azure subscriptions, populating them with diverse entities and configurable, traversable attack paths.
At a glance
- What is it?
- BadZure is an Apache-2.0 Python tool that deploys intentionally misconfigured Entra ID tenants and Azure subscriptions with Terraform, then layers privilege-escalation paths across the identity and resource planes on top. Every path starts from a foothold it hands you and ends at a high-privilege target, so you begin post-compromise rather than at the door.
- Who is it for?
- BadZure is a good fit for a detection engineer who needs realistic cloud telemetry to build a rule against, or a purple team that wants to rehearse a specific escalation technique end to end in a tenant it controls, since the foothold and the escalation path are both provided rather than something you have to construct.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 21 days ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A lab, not a scanner
BadZure automates the deployment of intentionally misconfigured Entra ID tenants and Azure subscriptions, populating them with diverse entities and configurable, traversable attack paths. The framing in the README is precise about the intent: it deploys misconfigured tenants so security teams can explore, exploit and detect cloud attack paths in a real environment. It uses Terraform to populate a tenant with users, groups, applications and Azure resources, then layers deliberate misconfigurations on top to produce complete privilege-escalation paths that span the identity and infrastructure planes. That last clause is the point of the project. A detection rule written against a diagram of Entra ID privileges is written against a guess, and this generates the environment where the guess can be tested. The tool was demonstrated at BlackHat Arsenal in 2024 and again in 2026, and the documentation is at badzure.com.
You start post-compromise, on purpose
The most important design decision is stated up front: every attack path begins at a compromised foothold and ends at a high-privilege target, and BadZure provides the foothold credentials, so you start post-compromise and focus on the escalation itself. That removes the most variable part of a cloud exercise, which is getting in, and lets a team spend its rehearsal time on the part that is actually hard. It also means the tool is not an initial access tool, and it does not need to be. The audience is listed as red teamers rehearsing Entra ID and Azure tradecraft in a safe disposable tenant, detection engineers and threat hunters generating attack telemetry to build and validate detections, purple teams reproducing a specific technique end to end from both sides, security researchers exploring cloud attack primitives, and trainers and capture-the-flag authors running practical cloud security labs. The last of those is a use that is easy to miss and is arguably the most valuable.
Two ways to author a path, and the seven templates
There are two authoring styles. An atomic path is one named technique template taken from a catalog of seven, and a chained path is an explicit graph built from lower-level primitives, where a chained path can either reproduce one catalog behaviour or combine several into a custom route. The seven atomic templates split across the two planes. The identity plane holds ApplicationOwnershipAbuse, ApplicationAdministratorAbuse and CloudAppAdministratorAbuse, which are all about a role that lets you modify application objects. The resource plane holds ManagedIdentityAbuse, KeyVaultSecretTheft, StorageCertificateTheft and CosmosDBSecretTheft, which are about turning an access path into data. The distinction between the planes is the reason the project is useful rather than merely destructive: an identity-plane escalation is invisible to a data-plane monitoring rule, and vice versa, so a lab that only contains one of them will produce misleadingly clean detection results. The technique catalog carries details and interactive graphs of each.
The command surface, from offline check to teardown
The tool is a single Python entry point with a set of subcommands, and the sequence matters. After cloning, creating a virtual environment and installing the requirements, you sign in with the Azure CLI, and the README notes that deploying requires Global Administrator in Entra ID and Owner on the subscription. Then the five commands:
python BadZure.py check --config badzure.yml # prove attack paths reachable (offline)
python BadZure.py report --config badzure.yml # render interactive graphs (offline)
python BadZure.py build --config badzure.yml # deploy the lab
python BadZure.py show # inspect what was created
python BadZure.py destroy --verbose # tear it all downThe ordering is the interesting part, because check and report are marked offline. You can validate that the attack paths are reachable and render the graphs before a single Azure resource exists, which is what makes it practical to review a lab design in a pull request. build is the only command that touches the cloud, show tells you what is currently there, and destroy is the one you will care about most, since Azure compute resources incur standard charges until you run it.
The dependency list, and what it reveals about scope
The requirements file is small and each entry points at a stage of the tool. requests, pyyaml, jinja2 and click are the working parts, python-terraform drives the infrastructure, cryptography handles credential and certificate handling, and python-dotenv reads the environment file. Then three optional entries with comments that are worth reading closely, because they tell you what the tool can do beyond Terraform. litellm is only needed for badzure generate, which is the LLM-authored configuration path, and it is a multi-provider client, so the model string selects the provider. azure-cosmos is only needed to plant cosmos_document data, which is the Python post-apply data-plane phase, so you can put actual documents in the Cosmos DB account rather than leaving it empty. And pytest runs the offline tests in the tests/ directory, which also self-run through python tests/test_*.py. The LLM configuration is set through the environment file, with the model default set to anthropic/claude-opus-4-1 and examples given for OpenAI, Gemini, a local Ollama model and a Hugging Face repository, plus an optional base URL override for local models, proxies or Azure OpenAI.
The repository layout and the author
The tree is organised around the paths rather than the code. The top level holds BadZure.py, the badzure.yml configuration, the terraform/ directory, src/, tests/, docs/, an entity_data/ directory, and an examples/ tree split into atomic/, chained/ and demo/ subdirectories, which mirrors the two authoring styles and gives you a working example of each. There is also a legacy/ directory, a mkdocs.yml for the documentation site, an .env.example to copy, and a .claude/ directory at the root, which suggests the project is developed with an AI assistant in the loop. The author is Mauricio Velazco, with contributors Chan Huan Jun and Manuel Melendez. The reference list is a good sign of where the project sits in the field, since it points at Cloud Katana for attack path mapping, AADInternals for Entra ID internals, ROADtools and PurpleCloud for enumeration, BloodHound and AzureHound for graph tooling, and the Azure AD Attack and Defense Playbook. The licence is Apache 2.0 and the last push was on 2026-10-02.
Where BadZure is the wrong tool
Three cases. The first is a production tenant, and this is not a nuance: the tool exists to install broken permissions on purpose, so running it anywhere that matters is the one thing you must not do. The second is a team that wants an assessment of a real tenant, because BadZure deploys a lab rather than auditing what is already there, so it does not answer the question of whether your own tenant is misconfigured, it answers the question of whether you can rehearse. The third is an environment where you cannot hold Global Administrator and Owner, since the tool is useless without those rights and the whole design assumes them. Against the alternatives the README lists, Cloud Katana maps attack paths in a tenant that already exists, BloodHound and AzureHound collect the graph data to do that, and ROADtools and AADInternals are the enumeration and research layers, so the difference in approach is that BadZure creates the broken state rather than finding it, which is the harder half of the problem and the one a detection engineer cannot do with an enumeration tool alone.
Editorial conclusion
BadZure is a good fit for a detection engineer who needs realistic cloud telemetry to build a rule against, or a purple team that wants to rehearse a specific escalation technique end to end in a tenant it controls, since the foothold and the escalation path are both provided rather than something you have to construct. It is a poor fit for a production tenant, since the tool exists to make a tenant maximally vulnerable, and it is a poor fit for anyone without Global Administrator rights in a disposable Entra ID tenant. Check three things before you run it: that you have a tenant and subscription you are willing to fill with deliberately broken permissions, since Azure compute resources incur standard charges until you destroy the lab, that the machine running it has the Azure CLI and Terraform installed, and that you read the required privilege level, which is Global Administrator in Entra ID and Owner on the subscription.
Frequently asked questions
What is BadZure?
It is a Python tool that deploys intentionally misconfigured Entra ID tenants and Azure subscriptions, using Terraform to populate a tenant with users, groups, applications and Azure resources, then layering deliberate misconfigurations on top to produce complete privilege-escalation paths spanning the identity and infrastructure planes.
What permissions does BadZure need to run?
Deploying requires Global Administrator in Entra ID and Owner on the subscription. You also need the Azure CLI and Terraform installed, and an Azure subscription with an Entra ID tenant, which the README notes can be created through the same flow.
What attack path techniques does BadZure ship with?
Seven atomic templates split across two planes. The identity plane covers ApplicationOwnershipAbuse, ApplicationAdministratorAbuse and CloudAppAdministratorAbuse, and the resource plane covers ManagedIdentityAbuse, KeyVaultSecretTheft, StorageCertificateTheft and CosmosDBSecretTheft. A chained path can be built from lower-level primitives to combine several into a custom route.
Can I validate a BadZure lab before deploying it?
Yes. The check and report subcommands are marked offline: python BadZure.py check --config badzure.yml proves the attack paths are reachable and python BadZure.py report --config badzure.yml renders interactive graphs, both without touching Azure. Only build deploys the lab, and destroy tears it down.
Does running BadZure cost money?
The README states that Azure compute resources incur standard charges until you destroy the lab, so the cost is the cost of the Azure resources the lab creates. The destroy subcommand is what stops it, and the show subcommand lets you inspect what was created.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/mvelazc0-badzure)Was this useful?