Nobody Shares the Key. Someone Mints It.

I modeled agentic lateral movement as a walk across shared secrets, then pointed it at a real Entra tenant and got zero pivots. The connector was not broken. A credential belongs to exactly one principal, and what moves an attacker sideways is the authority to mint a new one.

Share
Left: each service principal owns its own secret, so every pivot is a self-loop and the count is zero. Right: one Application Administrator fans out to every app it controls.
The literal ownership mapping yields zero traversable pivots. The pivot that exists is the authority to issue a credential for something else.

In my last post on agentic estates I argued that lateral movement between AI agents is a walk across shared secrets: one static API key baked into a fleet collapses the isolation between every agent that holds it, and the ATT&CK label on the move tells you nothing about how far it travels. I stand by the shape of that argument. I was wrong about the mechanism, in the specific place where it matters most, and I only found out by pointing the thing at a real identity provider.

The model, and the synthetic estate that validated it

The model adds three node types to the threat graph: agents, credentials, and tools. Agents hold credentials, credentials unlock agents, agents invoke tools, and the credential edges traverse in both directions. Compromise a credential and you can act as every agent it unlocks; compromise an agent and you inherit every credential it holds, which unlocks further agents. Each credential edge carries a success probability derived from posture rather than from the technique label, and the whole thing rides inside the same Monte Carlo breach computation as the technique walk, so a pivot moves breach probability instead of producing a "blast radius" number off to one side.

I validated that against a synthetic estate: a seeded set of agents sharing one static key, a scoped credential, a tool, each mapped to a real technique. It worked. A pivot edge flowed through the kernel and moved the number.

A synthetic seed proves the mechanism. It cannot prove the mapping. It tells you the machinery runs; it does not tell you that a real identity provider's objects project onto your topology, or that the pivots you expect survive contact with how credentials are actually issued. So I built a read-only connector against Microsoft Entra ID and ran it against a live tenant.

The connector returned zero pivots

Not one. Agents appeared, credentials appeared, and the pivot query came back empty.

The reflex is to go looking for the bug, and there wasn't one. The mapping was literally correct and structurally useless. In Entra a credential belongs to exactly one principal. A client secret is a secret of one application; a certificate is a key credential of one application. So the chain I had modeled, agent holds credential, credential unlocks agent, resolves to the same principal on both ends. Every candidate pivot is a self-loop. The query that defines a pivot as movement between two distinct principals discards all of them, correctly, and you are left with a graph that looks broken while being exactly right.

This is the failure mode I would not have caught in another year of unit tests, because the synthetic estate was built by someone who already believed the model. I seeded agents sharing a key because sharing a key was the thesis. Real directories do not hand out shared credentials. They hand out something worse.

The pivot is authority, not ownership

The real machine-to-machine lateral surface in Entra is role-based. A principal holding a credential-management role, Application Administrator, Cloud Application Administrator, Privileged Role Administrator, or Global Administrator, can add a new client secret to an application through the directory API, and then authenticate as that application.

It does not need to steal a credential. It mints one.

That is a different edge with a different meaning. Not "this credential belongs to me, and to you," but "this role lets me issue a credential for you." Once you model it that way the pivots reappear, and they land somewhere more interesting than where I expected: a small number of highly privileged principals, each carrying an UNLOCKS edge to every application it can control. Those roles are held by very few principals in a healthy tenant, which is precisely the point. They are the crown jewels, and after the correction the graph says so out loud instead of burying it in a list of technique labels.

The reframe for anyone building an inventory: the question is not "where are we reusing secrets." In a managed directory, largely nowhere. The question is who can issue a credential for something else, and how many somethings that covers.

Two axes, and they are independent

The correction split one intuition into two that behave differently.

Credential hygiene sets the probability on an edge. Posture still governs how likely an individual pivot is to work, and it binds to attributes you can actually read out of the directory:

Entra credential attribute Posture class Pivot success
Managed identity, no standing secret Delegation-attenuated 0.20
Certificate (key credential) Per-agent scoped 0.40
Client secret expiring within a year Shared but rotated 0.70
Client secret, long-lived or expired Static shared key 0.90

Credential authority sets how many edges a principal carries. Blast radius is structural. A broadly privileged principal is not a scarier single edge, it is the same edge repeated across a much larger fan-out, so it shows up in more paths and takes more of the risk.

Keeping those separate matters, because the combination that reads as safe is not. A short-lived managed identity attached to a Global Administrator role is a low-probability pivot with an enormous fan-out. Every hygiene dashboard you own will score it green. It has no standing secret to leak, no expiry to blow, nothing to rotate. It can also mint a credential for anything in the tenant. Hygiene tooling grades the 0.20 and never counts the edges.

What this changes about the shared-key story

Less than it looks, and in a way worth being precise about, because the two pictures cover different ground.

Inside a managed directory, ownership is one to one and the pivot is authority. Outside it, the original story holds without modification: the static key in a container image, the service token pasted into two CI pipelines, the one API key in the MCP server config that four agents point at. None of that is a directory object. Nothing issues it, nothing rotates it, and it is genuinely shared across principals in exactly the way my synthetic estate assumed.

So an agentic estate has two lateral-movement regimes running at once. The managed one, where you audit who can mint. The unmanaged glue between agents, where you audit what got copied. Most teams have a tool for the first and nothing at all for the second, which is roughly the inverse of where the drafting effort in this space has gone.

The pivot that leaves a log

One genuinely encouraging thing falls out of the correction. The stealthiest version of the old story, quiet reuse of a legitimate shared key, is nearly undetectable by construction: legitimate credential use looks like legitimate credential use. Minting is not like that. Adding a client secret to an application registration is a directory write, and directory writes are audited. The pivot leaves an event behind, attributable to the principal that performed it.

Which puts the burden back where I have put it before: the event exists, so the only question is whether anyone ingests it, whether a rule sits on it, and whether that rule's log source is actually present. A detection that would catch secret-minting but sits on a directory audit stream nobody onboarded is not coverage. This is the rare case where the telemetry is handed to you and the failure is entirely organisational.

What is validated, and what is not

Against a live tenant, read-only, I confirmed the object shapes the connector depends on: the service-principal and role-assignment projections, every field selected, the credential field names, the privileged-role identifiers. The connector reads machine principals only, service principals and managed identities, with two narrow scopes, and holds no ability to authenticate as or modify anything it inventories. Human users are deliberately excluded, because tens of thousands of interactive accounts would quietly change what a pivot means.

That validation pass is what surfaced the correction. A seed-and-prove harness then drove the connector's real client-credentials authentication path against the tenant and asserted that a seeded principal appears in the production pivot query rather than one written for the test. Insisting on the real auth path immediately surfaced a deserialization defect that every unit test had sailed past.

Two things I am not claiming. There is no end-to-end field study yet: the grounding establishes the topology and the mapping, not a distribution of breach-probability deltas across a production estate. And the four probability values remain reasoned priors. The tenant confirmed the credential classification, not the numbers, and the numbers stay published and revisable until a real distribution of credential scoping calibrates them.

What to do on Monday

  • Count the principals holding credential-management roles. Application Administrator, Cloud Application Administrator, Privileged Role Administrator, Global Administrator. That count is your agentic lateral-movement surface in the directory, and it is usually small enough to review by hand.
  • Treat those principals as crown jewels, not as configuration. Each one carries an edge to everything it can control. That is the fan-out that governs blast radius.
  • Stop reading "managed identity" as "contained." It removes the standing secret, which is real and worth having. It does nothing about authority, and authority is the axis that decides reach.
  • Inventory the unmanaged glue separately. Container images, CI variables, MCP server configs, .env files on developer machines. The shared static key is alive and well out there, and nothing in your directory posture tooling can see it.
  • Onboard the directory audit stream and put a rule on secret creation. This pivot writes to a log. Very few of the interesting ones do.

I published a model with an explicit prior and a stated mechanism, and the first contact with a real estate corrected the mechanism. That is the system working, and it is the argument for publishing the mechanism at all rather than shipping a score. A model that only emits a number cannot be wrong in public, which sounds like a feature until you realise it also means it can never be corrected. Mine was wrong about ownership, in a way a synthetic estate built by its own author could never have shown me, and the corrected version says something sharper than the original: in an agentic estate, the dangerous principal is not the one holding the most secrets. It is the one that can write new ones.


This post is the practitioner-facing version of a research whitepaper I wrote for AEGIS Labs, Agentic Identity Pivots: Modeling Credential-Borne Lateral Movement in Breach Simulation, updated to v1.2 with the Entra grounding described above. The posture-to-probability numbers are the model's published, revisable priors. All tenant work was read-only, against an estate I own.