Open your incident response runbook and time the containment section. Most read as a numbered list: disable the account, revoke the sessions, rotate the credentials it could reach, check the pipelines, page the platform team about the vault. Each step has an owner, each owner has a queue, and the sequence assumes hours of margin because the intruder needs hours too.

On 2 September 2026, Unit 42 published an investigation into a ransom operation that removes that margin: human-directed AI agent cyber attacks that compressed an enterprise intrusion into under 10 hours. A human operator delegated the tactical work to frontier AI agents and moved from an exposed web service to stolen root credentials, hijacked pipelines and abused cloud AI infrastructure in less than 10 hours, using more than 50 MITRE ATT&CK techniques. Unit 42's responders put the same work at roughly two weeks by hand.

Nothing in that chain is a technique your detections have never seen. What changed is the interval between them. A runbook that takes forty minutes to walk sequentially is not a containment plan against an adversary re-planning every few seconds — it is a way of arriving at each door shortly after it was used and closed behind them.

What follows is what the investigation documented, which parts are genuinely new, and how to rebuild containment for a Microsoft-centric estate so Entra revocation, service principal disablement, pipeline freeze and secret rotation happen as one action rather than five.


Ten Hours, Five Phases

The reported sequence is worth reading as a chain of dependencies rather than a list of tactics, because each phase hands the next one its input.

  1. Infiltration and mapping — the actor breached a publicly accessible web service to tunnel in, then deployed an automated recon agent to map internal microservices.
  2. Secrets harvesting — sub-agents combed enterprise code repositories for hard-coded tokens and service passwords.
  3. Privilege takeover — the exposed tokens opened the secrets management system, which yielded master administrative credentials and root access.
  4. Pipeline exploitation — CI/CD hijacking.
  5. AI infrastructure hijacking — stolen cloud keys turned the victim's own model endpoints into post-compromise infrastructure.

Two details stand out. The agents left forensically recognisable residue — structured Markdown files and generated scripts, artefacts of a machine writing notes to itself. And the operator had an agent produce an 80-page technical audit of the victim's security posture, cataloguing dozens of exploited findings. That is a negotiation lever, but also a confession: the intrusion produced more written analysis of the estate than most organisations manage about themselves in a year.

Unit 42's own framing is deliberately unglamorous. This was "AI-assisted operational efficiency, without the need for a novel zero-day or super elite tradecraft." Sanchit Vir Gogia of Greyhound Research reached the same read in CSO Online's coverage: "The evidence points to a human-directed intrusion in which AI orchestrated delegated tactical work."

The Operator Model

The structure matters more than the tooling. Unit 42 describes agents that "breached the company's security layers in a methodical manner, each targeting a different layer of defense to achieve a shared goal," with the division of labour set explicitly: "The actor sets objectives and makes consequential decisions. Specialized agents execute, share results and adapt in real time."

results shared,
plan revised in real time

Human operator
sets objective, makes
consequential decisions

Shared goal:
root access + leverage
for extortion

Agent: perimeter
public web service

Agent: internal recon
architecture + hosts

Agent: source repos
hard-coded tokens

Agent: secrets store
master credentials

Agent: CI/CD
pipeline hijack

Agent: cloud AI
stolen model keys

The dotted line is the load-bearing element. Agents report into a shared objective, the objective informs the operator, the operator re-tasks. No queue, no handover latency — results move between agents directly rather than through a person's attention.

AI Agent Cyber Attacks: Machine Speed, Familiar Tradecraft

Be precise about the novelty, because the wrong conclusion here produces the wrong spending.

Not new: every technique in the chain. Exposed web service, credentials in repositories, secrets manager pivot, CI/CD abuse. Unit 42's 2026 Global Incident Response Report, published 16 July 2026, makes the same point across its whole caseload — "The attacks observed in recent investigations are largely consistent with historical patterns."

Not new: the human. The operator chose targets, judged results and ran the extortion. Gambit Security's research into the Aurora ransomware crew's use of Cursor Agent found the same shape and the same limits — the agent was handed existing access, and the majority of its commands failed on the first attempt, requiring repeated human refinement. Delegated tactics, not delegated judgement.

Genuinely new: the collapse of the interval between phases, and parallelism across layers. A human who finds a token in a repository still decides serially what to try it against. Agents running in parallel try several at once and report back. The dwell time your playbooks assume — days of quiet lateral movement — is an artefact of human attention, not of the techniques.

Also new, and underrated: the estate's own AI infrastructure became a target. Stolen cloud keys were used against the victim's model endpoints, and the Global Incident Response Report flags token jacking — exposed credentials burned on cloud AI compute — as a rising category.

One adjacent data point is worth a sentence and no more. OpenAI's GPT-6 Astra reportedly scored 100% on ExploitBench, up from 78.5% for its predecessor, and the released model is restricted to secure code review and patching while refusing proof-of-concept exploit generation. Benchmark scores are not intrusions; the Unit 42 case used commodity capability well, not frontier capability at all.


Why Sequential Containment Loses

Now the arithmetic that should change your runbook.

Disabling an account in Entra ID does not stop an access token that has already been issued. revokeSignInSessions invalidates refresh tokens and browser session cookies by resetting signInSessionsValidFromDateTime, and Microsoft's documentation is explicit that "there might be a small delay of a few minutes before tokens are revoked." It also "doesn't revoke sign-in sessions for external users, because external users sign in through their home tenant."

Continuous access evaluation narrows that window for enlightened services. Admin revocation of refresh tokens is one of its critical events, and enforcement is near real time — but Microsoft states latency "of up to 15 minutes might be observed because of event propagation time." CAE also does not cover guest accounts, and CAE-aware sessions run long-lived access tokens of up to 28 hours. Without a CAE-capable client, your default access token lifetime is 1 hour.

So even a well-run revocation leaves a window measured in minutes, resource by resource. Against a human operator that is irrelevant. Against parallel agents re-planning continuously, minutes are enough to reach the next layer — which is why every layer has to shut at once rather than in your runbook's numbered order. Unit 42's first recommendation follows directly: automated playbooks that simultaneously revoke credentials, terminate OAuth sessions, freeze CI/CD pipelines and isolate cloud accounts.

Building the Simultaneous Runbook

Treat containment as one transaction with several writers. The pattern below fires identity, pipeline and secrets actions in parallel and reconciles afterwards; User.RevokeSessions.All is the least-privileged permission for session revocation. Start with the identity half, as a parallel block rather than a foreach loop:

# Identity containment: revoke sessions, disable accounts, disable service principals.
Connect-MgGraph -Scopes 'User.RevokeSessions.All','User.ReadWrite.All','Application.ReadWrite.All'

$compromisedUsers = @('svc-build@contoso.com','a.okafor@contoso.com')
$compromisedSpns  = @('11111111-2222-3333-4444-555555555555')

$jobs = @()
$jobs += $compromisedUsers | ForEach-Object -Parallel {
    Revoke-MgUserSignInSession -UserId $_
    Update-MgUser -UserId $_ -AccountEnabled:$false
} -ThrottleLimit 10 -AsJob

$jobs += $compromisedSpns | ForEach-Object -Parallel {
    Update-MgServicePrincipal -ServicePrincipalId $_ -AccountEnabled:$false
} -ThrottleLimit 10 -AsJob

$jobs | Wait-Job | Receive-Job

Pair that with a Conditional Access block policy scoped to the named users, held permanently in report-only and flipped to enabled during an incident. A pre-built policy you toggle is seconds; one you author under pressure is twenty minutes and a typo. If privileged accounts are activated just-in-time through PIM, note that ending an active role assignment and revoking the session are two separate actions — you need both.

The pipeline and secrets half runs at the same time, not after. gh workflow disable stops individual workflows; the repository-level Actions permissions endpoint stops everything in one call, which is what you want when you do not yet know which workflow was touched:

# Pipeline containment: freeze GitHub Actions and Azure DevOps, in parallel.
REPOS=("contoso/platform-iac" "contoso/payments-api")

for r in "${REPOS[@]}"; do
  gh api -X PUT "/repos/${r}/actions/permissions" -F enabled=false &
done

# Organization-wide equivalent: no repository may run Actions.
gh api -X PUT "/orgs/contoso/actions/permissions" -f enabled_repositories=none &

# Azure DevOps: disable the build definition that holds the service connection.
# queueStatus lives on the whole definition, so GET it, edit it, PUT it back.
(
  az devops invoke --org https://dev.azure.com/contoso --area build \
    --resource definitions --route-parameters project=Platform definitionId=42 \
    --api-version 7.1 --out-file def42.json
  jq '.queueStatus = "disabled"' def42.json > def42.disabled.json
  az devops invoke --org https://dev.azure.com/contoso --area build \
    --resource definitions --route-parameters project=Platform definitionId=42 \
    --api-version 7.1 --http-method PUT --in-file def42.disabled.json
) &

wait

Then the secrets layer. Disabling a secret version is faster and more reversible than rotating it, and it takes effect immediately — rotate afterwards, once you know which consumers you broke:

# Secrets containment: disable current versions of blast-radius secrets, then rotate.
VAULT=kv-contoso-prod

az keyvault secret list --vault-name "$VAULT" --query "[].name" -o tsv \
  | while read -r s; do
      az keyvault secret set-attributes --vault-name "$VAULT" --name "$s" --enabled false &
    done
wait

# Revoke the identity side of any workload credential the pipelines used.
az ad sp update --id 11111111-2222-3333-4444-555555555555 --set accountEnabled=false

The strategic fix is fewer things to revoke. Moving CI/CD off stored secrets and onto workload identity federation removes the credential class phase two depended on — an agent combing repositories finds nothing worth exchanging.

Models and API Keys as Tier-0

The investigation's second recommendation is a reclassification, not a product. A key that reaches your model endpoints is production infrastructure and should be governed like a domain admin credential.

  • Inventory. Every model endpoint, gateway and API key — including the one in a team's .env file and the one a vendor issued you. What is not on the list cannot be revoked during an incident, because nobody remembers it exists.
  • Scope. Least privilege and rate limits per key. A key that can call one deployment at a bounded rate turns token jacking from an open-ended bill into an alert.
  • Monitoring. Diagnostic logging on every endpoint, with unexpected model usage treated as a security signal rather than a cost anomaly. Cost dashboards find this eventually; detections find it in minutes.

Detecting Parallelism

Detection engineering is where the tempo insight pays off. Do not hunt for "AI" — hunt for the signature of a workload that never pauses: many distinct actions from one identity inside a window no keyboard produces.

One scheduled change first. AADSignInEventsBeta is deprecated on 19 October 2026 and replaced by EntraIdSignInEvents. Existing queries migrate automatically, but write new hunts against the new table. Both need Entra ID P2.

This surfaces breadth-per-identity — one account reaching an unusual number of distinct resources and applications in five minutes:

// Velocity: one identity, many distinct resources, tiny window.
EntraIdSignInEvents
| where Timestamp > ago(24h)
| where isnotempty(AccountUpn)
| summarize
    Resources = dcount(ResourceDisplayName),
    Apps      = dcount(Application),
    SrcIps    = dcount(IPAddress),
    Attempts  = count()
    by AccountUpn, bin(Timestamp, 5m)
| where Resources >= 6 or (Apps >= 4 and Attempts >= 40)
| order by Resources desc, Attempts desc

Tune the thresholds against your own baseline first; a sync service trips a naive version of this every night. Exclude by AccountObjectId, never by UPN pattern.

The second catches the same behaviour at the action layer using Defender for Cloud Apps activity, leaning on UncommonForUser — which flags event attributes anomalous for that specific account:

// Parallelism: distinct action types per identity per minute, weighted by anomaly.
CloudAppEvents
| where Timestamp > ago(24h)
| where AccountType != "System"
| summarize
    DistinctActions = dcount(ActionType),
    Apps            = dcount(Application),
    Anomalous       = countif(array_length(UncommonForUser) > 0),
    Sample          = make_set(ActionType, 12)
    by AccountObjectId, AccountDisplayName, bin(Timestamp, 1m)
| where DistinctActions >= 8 and Anomalous > 0
| order by DistinctActions desc

Both belong in Defender XDR's unified hunting surface as custom detections, with the containment runbook above wired as the response action rather than as a ticket.

Two non-query controls close the gap the intrusion actually exploited:

Mandatory multi-party review on IaC repositories. Non-bypassable branch protection on every repository that can change infrastructure. A required second approver stops an agent holding a valid token in a way no detection rule matches, because there is no anomaly to find — the commit looks legitimate.

Honeytokens where agents look. A plausible, unused credential in a repository, a .env template and the secrets store, wired to a high-severity alert with no legitimate consumer. Phase two was agents combing repositories for tokens; a decoy converts that phase from silent progress into a page.

The Mistakes a Fast Adversary Punishes

Four failure modes, each of which looks like diligence.

Treating "AI" as the threat category. Framing this as a self-directing AI agent cyber attack rather than a human directing agents mislabels the threat and misdirects the budget. The controls that would have changed this outcome are credential hygiene, branch protection and parallel containment. None are AI controls. Budget spent on AI-labelled tooling instead of those three is spent on the framing rather than the problem.

Blocking LLM domains as a control. Denying api.openai.com at the proxy stops nobody here — the agents ran on the attacker's infrastructure, so the model traffic never crossed the victim network. It also degrades your developers' work and pushes their usage onto unmanaged paths. Governing the model endpoints you own is the version that works.

SOC playbooks tuned for human dwell time. A 30-minute triage SLA, an escalation chain, a change-approval step before disabling a service principal. Each is reasonable against a human intruder and fatal against a ten-hour chain. Pre-authorise containment and decide in advance who may pull the trigger without a change ticket.

Defending against a fiction. The operator directed this, and Aurora's agent failed most first attempts. Defending against an imagined self-directing adversary produces paralysis; defending against a fast, well-instrumented human produces a runbook. A zero-trust posture that assumes lateral movement and segments accordingly beats any speculation about model capability.

Three Changes Worth Making Before Your Next Tabletop

In order; each is a week or less.

  1. Time your current containment sequence. Walk it end to end with a stopwatch in a lab tenant. That number is your adversary's budget. If it exceeds 10 minutes, the parallel rewrite above is the highest-value item on your backlog.
  2. Pre-stage the two artefacts you cannot author under pressure. The Conditional Access block policy in report-only, and the containment script with its Graph permissions already consented. Both are inert until an incident and useless if built during one.
  3. Run the tabletop on the compressed clock. Ten hours total, all five phases injected. The point is not to win it — it is to find which step in your process assumes someone will read an email.

The uncomfortable conclusion here is not that AI broke security. It is that the estate was already breakable, and the agents removed the delay that used to make it survivable. The 80-page report the attacker generated proves the findings were there to be found.

Related Articles

Thorsteinn Halldorsson Senior Cloud Engineer

Senior Cloud Engineer with 25+ years of hands-on experience across the datacenter-to-cloud stack: fiber SAN and disk storage, IBM/Lenovo blade and Dell/HP/Lenovo servers, Hyper-V and VMware clusters, and SQL and Remote Desktop Services (RDS) clusters. Deep in the Microsoft platform — Active Directory, PKI/certificate services, SQL, Power BI, Dynamics 365 Business Central (NAV) and AX (Axapta), Microsoft 365, Entra, and Intune — with a focus on Azure operations, FinOps, and applying AI tools like GitHub Copilot and Claude in real workflows. Writes practical, no-nonsense guides for IT professionals who need to ship real solutions.

Leave a Reply

Your email address will not be published. Required fields are marked *