Alert icon Keyboard navigation enabled.
Alert icon TAB or Shift+TAB to navigate across. Down ↓ to open menu. ESC to close menu.
Alert icon Down ↓ to select section. Right → to activate. Up ↑ / Down ↓ / Tab to traverse all. ESC to exit.
BeyondTrust
Skip to content Use space or enter to skip.

What can we help you find today?

Instant Results
  • Website Results
  • Technical Documentation

Filter Options

Focus your search

Filtering by

Your recent searches:

Contact Us Chat with Sales Get Support
  • English
  • Deutsch
  • français
  • español
  • 한국어
  • português
  • Home
  • Resources
  • Blog
  • Popping Microsoft’s Sandbox: Dataverse Security Risks in Plugin Containers current page
Link copied

Popping Microsoft’s Sandbox: Dataverse Security Risks in Plugin Containers

Jun 24, 2026

Dataverse security usually centers on access controls, roles, and environment governance, but this research examines what a custom .NET plugin could expose from inside a Microsoft Dataverse sandbox container.

Authors:
Simon Maxwell Stewart Headshot 2024
Simon Maxwell-Stewart
Staff Security Researcher
400x400 Linkedin X Profile
Phantom Labs™
BeyondTrust
BT Resources BLOG thumbnails 2000x2000 39
Popping Microsoft’s Sandbox: Dataverse Security Risks in Plugin Containers
Simon Maxwell Stewart Headshot 2024
Simon Maxwell-Stewart
Staff Security Researcher
400x400 Linkedin X Profile
Phantom Labs™
BeyondTrust

What Falls Out of a Dataverse Container

White chain icon to symbolize the ability to copy a link
Link copied
Check mark to visually show text has been copied

Microsoft Dataverse lets you deploy custom .NET plugins that run server-side in process-isolated Windows Server containers. We deployed one. Within minutes, we had SYSTEM privileges on the box, debug access to every running process, a production TLS private key for Microsoft's sandbox infrastructure, a live internal Microsoft API key verified against production endpoints, 51 other organization GUIDs from co-located tenants, and 69 proprietary Microsoft DLLs that were never meant to leave that container.

Background: How This Research Extends the Copilot Studio Security Series

White chain icon to symbolize the ability to copy a link
Link copied
Check mark to visually show text has been copied

Sometimes learning about Azure feels more like an exercise in archaeology than engineering. This is certainly the case when trying to learn Microsoft’s no-code AI agent building platform: Copilot Studio.

In Part 1 Copilot Studio AI agents security risks, Phantom Labs™ covered Copilot Studio and its underlying architecture, we covered the basics of Copilot Studio and its underlying architecture. To recap: Copilot Studio (formerly Power Virtual Agents) is part of the Power Platform, which was built around Dataverse (formerly the Common Data Service), a direct descendant of the Dynamics CRM data platform (XRM).

Figure 1: The madness of Azure’s naming (renaming) conventions

The importance of this lineage is that Copilot Studio AI agents can inherit some pretty old, wacky features from the XRM. This blog focuses on one of them: Custom API Plugins.

Custom API Plugins

White chain icon to symbolize the ability to copy a link
Link copied
Check mark to visually show text has been copied

Plugins were originally built for XRM to allow developers to register .NET assemblies against the platform’s event bus. This allowed for custom business logic in response to system messages triggered by events like record creation, updates, or deletion.

Custom API plugins extended this concept further, allowing developers to define their own custom messages. Once a Custom API Plugin has been registered, Dataverse exposes a full-blown Rest API endpoint to allow these custom messages to be triggered.

For example, a developer could define a new `ApproveExpenseReport` message and upload a .NET assembly to the Dataverse. After which, the Dataverse exposes the following:

```
`POST /api/data/v9.2/new_ApproveExpenseReport`
```

which will send an `ApproveExpenseReport` message to the registered .NET assembly.

Adventures Registering Our Own Plugin

White chain icon to symbolize the ability to copy a link
Link copied
Check mark to visually show text has been copied

Phantom Labs realised that we had many such .NET assemblies sitting in our out-the-box Dataverse environment and we were able to download and decompile the binaries to their source code using XRM Toolbox. After realising we could decompile these .NET plugins and inspect their source code, we became intrigued as to what kind of attack surface these plugins exposed. So we decided to register one.

Figure 2: Echo plugin that runs commands it receives as messages and returns the result

While this plugin allowed us to probe the environment, we quickly realized that more sophisticated attacks would be harder to execute. Since the plugin requests first hit a load balancer, meaning back-to-back calls were routed to different containers.

Instead, we used the Echo Plugin as a beachhead to setup a command and control (C2) channel via Azure Blob storage. Once active, the container polls an Azure bucket for commands and writes the results back to the C2 bucket, establishing persistent access for the lifetime of the container (~15-30 mins).

Figure 3: Our homespun C2

Getting SYSTEM on the Dataverse Container

White chain icon to symbolize the ability to copy a link
Link copied
Check mark to visually show text has been copied

Now that we’ve landed on the box as the user “user manager\containeradministrator”, which belongs to the “BUILTIN\Administrators” group. Moreover, inspecting the user’s security profile revealed critical privileges of the user were enabled:

  • SeDebugPrivilege: Open ANY process on the box regardless of its owner. Read/write its memory (e.g., dump any process, inject into SandboxWorker.exe, etc.)
  • SeImpersonatePrivilege: Steal another user's token and act on their behalf. Enables "potato" style attacks.
  • SeCreateGlobalPrivilege: Create objects in the global namespace.
  • SeChangeNotifyPrivilege: Bypass file/directory traverse checking. Minor but ensures you can walk any path on the system.
Figure 4: Our C2 in action, listing the privileges of the user running our plugin code

As a member of the Administrators group, we could interact directly with the Service Control Manager (SCM). This allowed us to create custom services and choose which user it will run under.

```
sc create SystemSvc binPath= "cmd.exe /c {COMMAND} > C:\Windows\Temp\output.txt" obj= LocalSystem
sc start SystemSvc
```

This registers and starts a new service called SystemSvc as the LocalSystem aka “NT AUTHORITY\SYSTEM”. Because this isn’t a proper service implementation, it ultimately errors out—but not before running our chosen command as SYSTEM and writing the output to a file.

What Falls Out

White chain icon to symbolize the ability to copy a link
Link copied
Check mark to visually show text has been copied

Now that we've escalated to SYSTEM on the box, let's do some fun things 😈.

SeDebugPrivilege is enabled by default, giving us debug access to every running process. Outbound HTTPS is completely unrestricted: no egress filtering, no proxy, no DLP. Anything we find, we can send straight to the internet.

Certificates and Private Keys

Next, we pulled the certificate store. The container held a TLS certificate and its corresponding RSA 2048-bit private key for `wus107.prd.sbx.dynamics.com`, a Microsoft-internal sandbox infrastructure hostname that doesn't resolve in public DNS. The private key is marked exportable and came out with a simple `certutil` call. This result was uploaded to our Azure Blob bucket over unrestricted outbound HTTPS.

Figure 5: A live TLS certificate we pulled from the box

We also found a self-signed worker certificate with a `Plex_Nonce` embedded in the Common Name. We'll come back to what that nonce is and why it matters shortly.

Process Memory

The Dataverse container runs a single critical process: `Microsoft.CDSRuntime.SandboxWorker.exe`, the gRPC worker responsible for executing plugins. With SeDebugPrivilege, we could read its entire address space.

We scanned 20 MB of the worker's memory and found 52 GUIDs that we can confirm are Dataverse organization IDs. Our own org ID appeared among them, positively identified via the sidecar's `GetWorkerAssignedMetadata` response (labeled as `CDS/OrganizationId:53c71faa-...`.

Out of the 52 GUIDs, 43 matched exactly with org IDs found in the sidecar's `AppInsightsConnectionString`, a telemetry routing table that maps every organization on the cluster to its instrumentation key. The remaining 9 GUIDs did not appear in the sidecar data, leaving their origins unknown. This cross-tenant information leak was confirmed with Microsoft on a call.

The Plex DLL Stack

We also walked away with 46 proprietary Microsoft DLLs comprising the entire Plex infrastructure stack. After decompiling them into roughly 14,000 C# source files using ILSpy, what began as a container escape turned into a full infrastructure audit.

The decompiled source revealed a host-side service called the "sidecar" that the worker connects to on startup, the methods it exposes, the parameters they accept, and how authentication is (or isn't) enforced.

Environment Variables

Next, we dumped the container's environment variables. Buried within the standard Windows noise, `sidecarIP` and `SideCarShimEndpointPort` gave us the address of the host-side gRPC sidecar service.

The `Plex_Nonce` is a 128-bit GUID that turned out to be the sole authentication credential required for the worker execution RPC. Meanwhile, `AzureTenantId` contained four Microsoft tenant IDs, including `microsoft.com` corporate (`72f988bf`) and `dynamics.com` (`f8cdef31`). Finally, the `CS_CLUSTER*` variables revealed the infrastructure topology: cluster `prdil107wus`, type `islandcluster`, and region `westus`.

Figure 6: A partial snapshot of the Environment variables revealing the sidecar configuration

With the decompiled source code, an IP address, a port number, and a stolen nonce, it was time to see what the sidecar had to say for itself.

The gRPC Architecture

White chain icon to symbolize the ability to copy a link
Link copied
Check mark to visually show text has been copied

The decompiled source revealed a four-tier gRPC architecture that Microsoft calls "Plex." We reconstructed the full service definitions from the C# stubs and published them as an OpenAPI specification alongside Go tooling (link below). We also published a website called plex-explorer, documenting the plex architecture.

Figure 7: A snapshot from plex-explorer showing the sandbox architecture
  1. Platform is the Dataverse application server tier. It dispatches plugin execution requests, processes all plugin callbacks (data queries, token acquisition), and makes every authorization decision. If a plugin wants to read data or get a token, the platform decides whether to allow it.
  2. Gateway sits between the platform and the worker pool. It routes execution requests to available workers and relays callbacks back in the other direction. It does not make authorization decisions itself. The platform authenticates to the gateway with JWT tokens, and the gateway authenticates to workers with a per-worker nonce.
  3. Worker is a .NET process running inside a Hyper-V isolated container. It hosts plugins and listens on port 9000 for gRPC Execute calls from the gateway. When a plugin needs to talk to Dataverse, the worker proxies the request back up through the same bidirectional gRPC stream. The container runs as ContainerAdministrator with SYSTEM-equivalent privileges, but the Hyper-V boundary is what's supposed to keep that contained.
  4. Sidecar is a host-side gRPC service running outside the Hyper-V container on the same physical node. It provides environment configuration, token acquisition, extension loading, and telemetry across 22 methods. None of them require authentication. No token, no certificate, no API key.

What the Sidecar Returns

We called every sidecar method without any credentials. The headline discovery: GetEnvironmentVariables hands back the Plex_Nonce, four Microsoft tenant IDs, the full cluster configuration, and a telemetry routing table mapping all 43 co-located org IDs to their AppInsights instrumentation keys. Additionally, GetOpenIdSigningKeys returns a full JWKS containing RSA public keys and X.509 certificate chains.

Figure 8: Our reverse engineered swagger docs, showing the Sidecar’s gRPC methods

Seven write methods also accepted calls without authentication, covering worker lifecycles, crash events, metric injection, and port proxy creation. We also tried testing the extension-loading methods (`LoadExtensionPackage`, `LoadHostInjectionPackage`, `LoadDataverseExtensionAssembly`). None returned data for any input we tried.

Impact: Cross-Plugin Attacks

White chain icon to symbolize the ability to copy a link
Link copied
Check mark to visually show text has been copied

Plugins from the same organization share a container pool. We confirmed this by registering a second plugin and observing both executing on the same container, sharing a filesystem and process space.

In production, organizations routinely install third-party plugins from Microsoft AppSource, which lists over 665 Dataverse solutions. Because these plugins handle financial data, PII, CRM records, and authentication tokens, having them co-located next to an attacker-controlled plugin with SYSTEM privileges means a single malicious installation can immediately pivot to intercepting legitimate plugin traffic.

We proved this by using the malicious plugin’s ability to debug process memory and set up an interceptor that periodically scans the workers memory, catching the data going in and out of legitimate plugins co-located on the same container pool.

Our PoC injected a unique marker into a payload sent to another legitimate plugin; the malicious plugin scanned for this marker in memory and pulled the surrounding payload data, confirming that we were able to catch the payload in the worker’s memory.

In a real attack—given the worker has full internet access—the interceptor would likely just periodically dump all the worker’s memory to a blob storage for offline analysis.

Figure 9: A malicious plugin can intercept the data of another legitimate plugin co-located on the same container by simply scanning the containers memory.

We also attempted a DLL cache poisoning attack by replacing a legitimate plugin's cached assembly on the shared filesystem with a trojaned version. Alarmingly, the worker loads whatever binary it finds in the cache without re-verifying signatures. Ultimately, SYSTEM on a shared container opens many doors—memory interception and cache poisoning are just two methods among many potential vectors.

Microsoft’s Response

White chain icon to symbolize the ability to copy a link
Link copied
Check mark to visually show text has been copied

After sharing the findings and writeup to Microsoft, they asked we don't refer to this primitive as a "container escape". Their position is that getting SYSTEM on the box via user supplied code is part of their threat model for sandbox containers. Their exact quote from our discussion:

“As discussed, the container is treated as a hostile, multi-tenant environment within our security model.” --MSRC, June 22 2026

However, when Phantom Labs looked through the Dataverse plugin docs (June 5th 2026) we could not seem to find Microsoft’s portrayal of this security model stated anywhere clearly. Rather, their documentation on how to “write custom Azure-aware plugins” stated the following:

Figure 10: Previous Microsoft Plugin document stating “No other external access, such as access to a local file system, is allowed.”

The line “No other external access, such as access to a local file system, is allowed” was dropped sometime after this screenshot was taken. As this was a stated boundary of the security model prior, Phantom Labs stands by the “container escape framing”.

Figure 11: Microsoft’s updated docs which removed: “No other external access, such as access to a local file system, is allowed.”

As part of this research, we have released Plex Explorer, a live website detailing the plex architecture and the tooling we used to probe sandbox containers.

  • Plex Explorer – https://plex.btphantomlabs.com/
  • Probing tooling (including gRPC implementation) - https://github.com/beyondtrust/plex-explorer

Explore More Research from Phantom Labs

White chain icon to symbolize the ability to copy a link
Link copied
Check mark to visually show text has been copied

Phantom Labs™ researchers "think like attackers" to expose privilege escalation paths and identity attack vectors, helping defenders proactively uncover misconfigurations and detect emerging identity, cloud, and AI security threats in complex hybrid and cloud environments. Using advanced graph modeling, Phantom Labs researchers map attack paths to privileged access across cloud and on-premises infrastructure.

Continue Reading

White chain icon to symbolize the ability to copy a link
Link copied
Check mark to visually show text has been copied
  • https://www.beyondtrust.com/blog/entry/copilot-studio-ai-agents-security-risks
  • https://www.beyondtrust.com/webinars/ai-hacking-weaponizing-enterprise-agents
  • https://www.beyondtrust.com/blog/entry/restless-guests
  • https://www.beyondtrust.com/blog/entry/evil-vm

About the Author

White chain icon to symbolize the ability to copy a link
Link copied
Check mark to visually show text has been copied
Simon Maxwell Stewart Headshot 2024
Simon Maxwell-Stewart
Staff Security Researcher

Simon Maxwell-Stewart is a University of Oxford physics graduate with over a decade of experience in the big data environment. Before joining BeyondTrust, he worked as a Lead Data Scientist in healthcare, and successfully brought multiple machine learning projects into production. Now working as a "resident graph nerd" on BeyondTrust's security research team, Simon applies his expertise in graph analysis to help drive identity security innovation.

400x400 Linkedin X Profile
Phantom Labs™
BeyondTrust

BeyondTrust Phantom Labs™ believes the best way to fully understand cybersecurity threats is to work closely with our customers and partners, conducting real world research into the attacks that matter most to them. By dissecting emerging attack methods and exploitation techniques of threat actors, as well as conducting novel research, the team’s mission is to help organizations defend against identity threats. 

Latest Posts
  • Mapping Every Privilege Escalation Path in AWS AgentCore
    Jun 15, 2026 Mapping Every Privilege Escalation Path in AWS AgentCore
    Blog
    12m
  • Hooked on Identity (Part 2): Abusing OAuth Trust Boundaries in Okta
    Jun 12, 2026 Hooked on Identity (Part 2): Abusing OAuth Trust Boundaries in Okta
    Blog
    7m
  • Hooked on Identity: Abusing SAML Assertion Inline Hooks in Okta
    Jun 9, 2026 Hooked on Identity: Abusing SAML Assertion Inline Hooks in Okta
    Blog
    6m
  • Joining Project Glasswing: Securing the Privilege Backbone of the AI Era
    Jun 8, 2026 Joining Project Glasswing: Securing the Privilege Backbone of the AI Era
    Blog
    5m
  • The Most Common & Most Dangerous Types of Shadow IT
    Jun 5, 2026 The Most Common & Most Dangerous Types of Shadow IT
    Blog
    19m
Related
  • What Is a BEC Attack? Examples and Prevention
    Aug 26, 2025 What Is a BEC Attack? Examples and Prevention
    Blog
    7m
  • True Privilege™: BeyondTrust Sets New Standard for Privileged Access and Identity Security
    Sep 5, 2025 True Privilege™: BeyondTrust Sets New Standard for Privileged Access and Identity Security
    Blog
    3m
Share this Article
  • Link
Tags
  • BeyondTrust Phantom Labs
  • Phantom Labs
  • Phantom Labs Research
  • The BeyondTrust Research Team
Stay up to Date
Get the latest news, ideas, and tactics from BeyondTrust. You may unsubscribe at any time.

Keep up with BeyondTrust

Customer Support Get Started
  • LinkedIn
  • X
  • Facebook
  • Instagram
  • Add BeyondTrust as a preferred source on Google
  • Privacy
  • Security
  • Manage Cookies
  • Do Not Sell My Data
  • WEEE Compliance

Copyright © 2003 — 2026 BeyondTrust Corporation. All rights reserved. Other trademarks identified on this page are owned by their respective owners. BeyondTrust Corporation is not a chartered bank or trust company, or depository institution. It is not authorized to accept deposits or trust accounts and is not licensed or regulated by any state or federal banking authority.

Prefers reduced motion setting detected. Animations will now be reduced as a result.