// threat intel

JADEPUFFER Ran an Agent-Driven Azure Wipe in 18 Hours. The Way In Was a Secret in a GitHub Issue’s Edit History

In early June, a threat actor Microsoft tracks as JADEPUFFER (also Storm-3168) ran a full agent-driven attack against an Azure tenant: 16 hours of automated reconnaissance, then 35 minutes of destruction that tried to delete more than 100 storage accounts and deliberately went after backup and recovery resources first. Microsoft calls it an example of agentic-driven cloud attacks, part of a shift toward AI-orchestrated operations that coordinate complex post-compromise work across cloud environments at speed and scale. We build offensive tooling against exactly this class of adversary, so it is worth being precise about what actually happened and where it was preventable.

The headline everyone will take is “AI wiped a cloud tenant.” The lesson underneath is quieter and more useful: the agent was fast and autonomous, but the door it walked through was a plaintext credential a human left in a public GitHub issue.

JADEPUFFER attack timeline: 16 hours and 300+ read operations for reconnaissance, then 35 minutes and 150+ operations for destruction, collapsing into a 7-minute deletion sequence with 100+ storage accounts targeted

How they got in: a secret that outlived its deletion

The initial access was not clever. An employee pasted service principal credentials, the client ID, client secret, and tenant ID, into a public GitHub issue. The secret was later removed. But it stayed reachable through the issue’s public edit history, which is not something a quick “oops, deleted it” ever cleans up. A service principal is a non-human identity with real standing access to the tenant, and once its credentials are public, anyone can authenticate as it.

This is the exact failure mode we have written about before: secrets sprawl is a non-human identity problem, not a coding problem. A leaked service principal is a machine identity with standing privileges that nobody scoped down, rotated, or watched. The GitHub edit-history detail is worth internalizing, because deleting a secret from a public surface does not un-leak it. If it was ever committed, pasted, or shown, treat it as burned. This is precisely the kind of exposure a secure code review and secrets-hunting across your public surface is meant to catch before an attacker does.

What the agent did with that access

Once authenticated, the operation ran with a discipline that reads as automated, not hand-driven. Microsoft observed two compromised service principals splitting the work inside the same tenant: one for reconnaissance and discovery, one for destruction and credential collection. That division of labor is a design choice, and it is the tell of an orchestrated attack rather than a person clicking around.

The tempo is the part to sit with:

  • 16 hours of reconnaissance, 300+ read operations. Enumerated VMs, subscriptions, resource groups, and Azure App Service configuration stores (the last almost certainly hunting for more exposed credentials). At one point it enumerated resources across two subscriptions in five seconds.
  • 35 minutes of destruction, 150+ operations. It went after backup and recovery resources first, to cripple the victim’s ability to recover, then moved to mass deletion.
  • A 7-minute deletion sequence with 100+ storage-account deletion attempts.

Previous JADEPUFFER activity, documented by Sysdig in July, showed the fuller shape: an autonomous agent that reasoned about its targets, harvested and reused credentials, moved laterally, established persistence, and destroyed a database. The group has also deployed ENCFORGE, Go-based ransomware that specifically scans for AI infrastructure, roughly 180 file extensions including model checkpoints, vector databases, training datasets, and embedding indices. This is an adversary that both uses agents to attack and targets AI systems as the prize.

What actually blunted it

Here is the constructive part, because not everything the agent tried succeeded. Azure resource locks and storage-account-level deletion protection blocked some of the deletion attempts. Azure SQL database deletions failed because the agent used an unsupported API version. Key Vault, Function Apps, App Service plans, VMs, and recovery protection locks were targeted but partly survived.

Read that carefully, because it is the whole defensive argument. An autonomous agent moving at machine speed still hit hard controls it could not reason past. Resource locks and deletion protection are boring, unglamorous config, and they are exactly what stood between “some resources deleted” and “tenant gone.” Speed does not beat a control that is actually in place. It only beats controls you assumed were there and never verified. Whether your Azure locks, deletion protection, and service-principal scoping actually hold up under an attacker who already has one valid credential is a concrete, testable question, and it is what a Azure penetration test and a cloud configuration review answer.

What held versus what fell in the JADEPUFFER attack: resource locks, SQL API mismatch, and deletion protection blocked some destruction, while 100+ storage accounts had no protection and were targeted for deletion

The reframe: govern the identity, because you cannot outpace the agent

You are not going to react faster than an agent that enumerates two subscriptions in five seconds and deletes a hundred storage accounts in seven minutes. Trying to win on speed is a losing race. What you can control is what the compromised identity is allowed to do before anyone is watching. That means scoped, short-lived credentials instead of standing service-principal secrets; resource locks and deletion protection on anything whose loss would hurt; and monitoring on the machine identities themselves, not just the humans.

This maps directly onto what we build and test:

  • The leaked service principal with broad standing access is a non-human identity governance failure. Inventorying what your machine identities can actually reach, and proving it from an attacker’s seat, is core to AI agent penetration testing and our identity work.
  • On the outbound side, an agent (yours or a compromised one operating in your tenant) acting on credentials it should never use is exactly what our firewall airlock_ai sits in front of.
  • The reconnaissance phase, where the agent hunts App Service config stores for more credentials, is a trap surface. BastionAgent seeds dead watermarked credentials exactly where a reasoning agent expects to find them, so a credential-hunting agent declares itself the moment it acts, and its 16-hour quiet recon becomes a logged, attributed event instead of an invisible prelude to a wipe.

The takeaway

JADEPUFFER is a preview of the ordinary cloud incident, not an exotic one. The agent supplied the speed and the coordination, but the breach was a leaked machine identity with standing access that nobody rotated after it hit a public surface, and the damage was bounded almost entirely by whether basic Azure protections were switched on. That is the whole playbook to defend against: assume any secret that ever touched a public surface is compromised, scope and shorten your machine-identity credentials, turn on resource locks and deletion protection before you need them, and then have someone prove those controls hold against an attacker who already has a valid credential. You cannot out-react the agent. You can make sure the identity it steals cannot do much, and that it trips a wire the moment it tries.


// get started

Work with AgentOffense

Tell us about your target and goals. We’ll reply with scope and a fixed-price quote — usually within one business day.

./request_engagement