On 25 September 2026 Microsoft published the cloud half of a story the industry had only seen from the inside of a container. Two compromised Azure service principals in one tenant ran fifteen hours of reconnaissance, deleted more than a hundred storage accounts in about seven minutes, and then came back for the access keys. Microsoft names no vulnerability anywhere in that sequence. Every destructive call was authorised by a role assignment that already existed.
TL;DR
- Microsoft published the investigation on 25 September 2026 and tracks the actor as Storm-3168, which it links to JADEPUFFER.
- Two service principals from the same tenant were used. The first ran reconnaissance for about 15.5 hours with over 300 successful read operations. The second did discovery, destruction and credential collection.
- Per Microsoft, a group-granted Storage Account Contributor role authorised the destructive storage operations, and direct Contributor access authorised three application-resource deletions.
- The client ID, client secret and tenant ID had previously appeared in plaintext in a public GitHub issue. The secret was edited afterwards and stayed readable in the edit history. Microsoft could not definitively confirm this led to the compromise.
#What Microsoft documented
JADEPUFFER was already on record. Sysdig described it in July 2026 as the first documented agentic ransomware operation, and we traced that container-side path in an earlier teardown. What Microsoft added last week is the control-plane view: what the same cluster of activity looks like from inside an Azure tenant, written from Microsoft's own telemetry rather than from a recovered staging server.
The answer is unglamorous, which is the point. There is no new technique in the report. There is a workload identity with a secret that leaked, a set of role assignments nobody had revisited, and an operator moving fast enough that Microsoft describes the timing as consistent with automated or scripted execution.
Microsoft also notes that Storm-3168 had been probing Azure App Services since early 2026, but that per the report this probing did not overlap with the affected subscriptions. Worth keeping separate from the main story.
#The access path, step by step
# as published by Microsoft, 25 September 2026 public github issue # client id, client secret and tenant id in plaintext → edit history # secret edited out later, still readable → service principal# two principals in the same tenant → role assignments # Storage Account Contributor via a group, plus Contributor → storage accounts # 100+ deletion attempts, most succeeded → account keys # 30+ successful ListKeys requests after the wipe
Read that path as an identity story and the shape is familiar. A secret for a non-human identity ends up somewhere public. Nobody rotates it, because nobody is watching that identity. The identity carries standing permissions that were granted for an operational reason years of tickets ago. The permissions are the payload.
#The roles did the damage
This is the sentence from the Microsoft write-up worth pinning to a wall: the Storage Account Contributor role was granted through a group, and that group membership authorised the deletions. Nobody assigned a destructive role to a service principal on purpose. The principal was in a group, the group had a role, and the role allowed delete.
| Operation | What authorised it |
|---|---|
| 300+ read operations over 15.5 hours | Normal read access on two subscriptions |
| Enumerating VMs and resource groups in 5 seconds | The same read access |
| 100+ storage account deletion attempts | Storage Account Contributor, granted via a group |
| Key Vault, Function App and App Service plan deleted | Direct Contributor access |
| 30+ ListKeys requests for storage account keys | The same role, after the destruction |
Every row is an authorised call. A policy engine asked, correctly, whether this principal may delete this storage account, and the answer was yes. The finding only exists when the rows are joined up into a path, which is the same shape we traced through an OAuth token at Vercel and through a service account at 395 organisations.
Group-granted roles are the detail most inventories miss. Ask your cloud team which service principals can delete a storage account and you will get a list built from direct assignments. The principal in this incident would not have been on it.
#Thirty-five minutes
The reconnaissance was patient. The destruction was not. Ninety minutes after the first reads, the second principal enumerated virtual machines and resource groups across two subscriptions in five seconds. Seventy seconds after the final inventory call it tried a ListKey operation against a storage account that did not exist, and less than a second after that failure the deletions began.
Microsoft reads the coordination between those operations as automated or scripted execution, and says the activity is consistent with tactics that can support ransomware and extortion operations. Two deletion tokens running in parallel is the detail that makes a human operator hard to picture.
What that timing does to a response plan is simple and uncomfortable. A 35 minute window is shorter than most alert triage. Containment that depends on a person reading a notification has already lost. The only control that operates on that timescale is the one that was in place beforehand: what the identity was allowed to reach.
#The part after the wipe
About thirty minutes after the destruction, the same principal inventoried storage accounts again and issued more than thirty successful ListKeys requests for account access keys, including accounts related to Site Recovery. That is the step most summaries skip, and it is the one that matters longest.
Deleted resources are a recovery problem. Leaked storage account keys are an access problem that outlives the incident. A storage account key is a static shared secret, it is not tied to any identity, and it keeps working until somebody rotates it. If more than thirty of them left a tenant, the clean-up is not finished when the resources are restored.
Microsoft also records that some destruction failed. Resource locks blocked part of the storage deletions, the Azure SQL deletions failed on an unsupported API version, and attempts against Site Recovery and Backup protection locks were unsuccessful. Locks on recovery infrastructure did real work here.
#What to check this week
- List every service principal that can delete. Resolve group-granted roles, not just direct assignments. Storage Account Contributor, Contributor and Owner on any subscription or resource group are the ones to pull first.
- Search your public repositories for tenant IDs and client secrets, including issues, pull request comments and edit history. Microsoft's own guidance is to treat a publicly exposed credential as compromised even if the original location was edited or deleted.
- Rotate storage account keys and move consumers to Entra authentication. A shared key reaches data without an identity attached, so no conditional access policy and no sign-in log applies to it.
- Alert on ListKeys at volume. Thirty key retrievals from one principal in half an hour is not operational behaviour. This is a cheap detection and almost nobody has it.
- Put resource locks and backup protection on the things you cannot rebuild. They are what blocked part of this attack, and the attempts to remove them are themselves a signal.
- Give every service principal an expiry and an owner. A secret with no rotation date and no named owner is the identity this path depends on.
On Elmoz
#FAQ
What is Storm-3168?
Storm-3168 is the designation Microsoft uses for the threat actor behind the Azure activity published on 25 September 2026. Microsoft links it to JADEPUFFER, which Sysdig described in July 2026 as the first documented agentic ransomware operation.
How did the attacker get the service principal credentials?
Microsoft reports that the client ID, client secret and tenant ID had previously appeared in plaintext in a public GitHub issue posted by an employee of the affected organisation. The secret was edited later but stayed readable in the edit history. Microsoft could not definitively confirm that this was the source of the compromise.
Was an Azure vulnerability exploited?
Microsoft does not describe one. Per the report, a group-granted Storage Account Contributor role authorised the destructive storage operations and direct Contributor access authorised three application-resource deletions. The operations were allowed by existing role assignments.
What stopped parts of the attack?
Azure resource locks blocked some of the storage account deletions. Attempts against Azure Site Recovery locks and Azure Backup protection locks were unsuccessful, and the Azure SQL database deletions failed because of an unsupported API version.
An agentic operator does not need a new technique when a workload identity already reaches the data. Elmoz maps AI agents and non-human identities across cloud and SaaS, resolves group-granted roles, and shows which access paths end at data that matters.