Microsoft Execution Containers Are Generally Available: An Agent Cannot Be Its Own Security Authority
💡 Tool Tip:YAML to JSON, Diff Checker, JSON Formatter, Regex Tester
Microsoft took Microsoft Execution Containers to general availability on October 7, 2026. The framing in Microsoft's own announcement is worth reading twice: an agent cannot be its own security authority. That single sentence is the whole idea. MXC is a policy-driven execution layer for code you did not write and cannot fully predict - model output, plugins, tools, the harness, or the entire agent. Developers and administrators declare which files and network destinations may be used, and Windows selects an appropriate container to enforce those declarations at runtime.
The boundary has to live outside the workload you do not trust
What MXC actually is
MXC is a policy-driven execution layer for untrusted or dynamically generated workloads. In agentic use, that means you can contain model-generated output, plugins, tools, an agent harness, or the agent as a whole. The scope is the thing you choose. Microsoft is explicit that the goal is limiting what the agent workload can access, which caps the blast radius when something goes wrong rather than pretending nothing will. It is now generally available, not a preview, so the design assumption shifts: this is something you are meant to configure in production, not evaluate.
# mxc-policy.yaml - declare the boundary, do not hope for good behaviour.
# MXC is policy-driven: the developer or IT admin names the resources,
# and the platform picks a container that enforces the policy at runtime.
version: 1
agent: invoice-triage
filesystem:
read:
- C:\work\inbox\** # the only place inputs live
write:
- C:\work\outbox\**
deny:
- C:\Users\**\AppData\** # credential stores, browser profiles
- C:\Windows\**
network:
allow:
- https://api.internal.example.com # the one API it needs
deny: ['*'] # default deny, not default allow
process:
allow_spawn: false # no sub-processes, no shells
Containment, identity, manageability
Microsoft splits the problem into three parts and only one of them is a container. Containment limits what an agent can access and do. Identity distinguishes an agent's activity from a person's, and Windows will soon enable Microsoft Entra to do exactly that - which matters because an agent inheriting a human's credentials is the root of half the audit stories you read. Manageability gives organisations the tools to govern access and monitor activity, extending Microsoft Agent 365 controls to local agents on-device so IT can manage MXC containers, apply policy and watch what agents do. Containment alone is a wall with no camera.
# An agent cannot be its own security authority: the check must sit
# outside the agent's code path, in the layer that calls the tool.
import os, pathlib
ALLOWED_DIRS = {pathlib.Path(r'C:\work\inbox'), pathlib.Path(r'C:\work\outbox')}
def guarded_write(path: str, data: str, policy: dict) -> None:
p = pathlib.Path(path).resolve()
if not any(p.is_relative_to(d) for d in ALLOWED_DIRS):
raise PermissionError(f'policy deny: {p} is outside the declared roots')
if any(p.match(pat.replace('\\', '/')) for pat in policy['filesystem']['deny']):
raise PermissionError(f'policy deny: {p} matched a deny rule')
p.write_text(data, encoding='utf-8')
# The model never sees this function. That is the point.
Enforcement happens at runtime, not at review time
Why the agent cannot police itself
If the agent decides whether its own action is allowed, you have a suggestion, not a control. The workload is exactly the thing under test; it cannot also be the judge. That is why the useful engineering question is not 'put the agent in a container' but 'where does the enforcement decision live, and can the workload reach it?' MXC answers by moving the decision into the operating system, outside the agent's code path. Any policy the agent can edit, bypass or argue with is decoration. The test is simple: can the model's output, on its worst day, change the rule that governs it?
# Roll out in one team before you roll out to the fleet.
# Effective policy is the only policy that counts.
ANIMALS = 'invoices'
mxc canary --policy mxc-policy.yaml --tag canary --percent 5
mxc policy show --agent invoice-triage --effective # what Windows will enforce
mxc policy diff --agent invoice-triage --effective --declared
# Look for the two failure modes that hurt:
# declared_but_not_enforced -> a false sense of safety
# enforced_but_not_declared -> a surprise outage waiting to happen
Policy that outlives the prompt
Prompts change daily. Policy should change on purpose, with a review. Writing the boundary as declarative policy rather than as instructions inside a prompt is what makes it survive a model swap, a framework upgrade or a new tool integration. The practical shape is a file like mxc-policy.yaml: read these directories, write to those, reach this one API, deny everything else, and do not spawn processes. It reads like a firewall rule set because it is one. The corollary is that policy now needs version control, review, and a diff - and the diff is where most of the value shows up.
# Reconstruct what happened after the fact. Without this, a containment
# boundary is a claim, not a control.
import json, time
def audit(record, decision, reason):
return json.dumps({
'ts': time.strftime('%Y-%m-%dT%H:%M:%S%z'),
'agent': record['agent'],
'tool': record['tool'],
'target': record['target'], # file path or network destination
'decision': decision, # allow | deny
'reason': reason, # which rule fired
'policy_rev': record['policy_rev'], # policy version in force at the time
}, ensure_ascii=False)
# Log policy_rev on every call. A deny you cannot explain is a deny
# nobody will trust, and an unused policy is worse than no policy.
Declare the policy, then test it against real tool calls
What containment does not fix
MXC does not tell you whether the agent picked the right file, only whether it was allowed to. It does not stop a prompt injection that convinces the model to exfiltrate a document it legitimately has access to - the call is in policy, the intent is not. It does not replace secret management, because a contained agent with a live API key can still spend your money. It does not fix a tool surface that is simply too large. And it does not help you if the policy is declared but never verified as enforced, which is the most common failure in every control system ever shipped.
# Measure the gap between the tool surface you think the agent has
# and the tool surface it actually exercises in production.
from collections import Counter
def policy_coverage(audit_rows, declared_rules):
used = Counter(r['tool'] for r in audit_rows)
denied = sum(1 for r in audit_rows if r['decision'] == 'deny')
uncovered = [t for t in used if not any(t in rule for rule in declared_rules)]
return {
'distinct_tools_used': len(used),
'deny_rate': round(denied / max(len(audit_rows), 1), 4),
'tools_with_no_rule': uncovered, # tighten these first
}
# A deny rate near zero in week one usually means the boundary is too
# loose, not that the agent is well behaved.
A rollout sequence that will not page you
Start with one agent in one team at low volume, and read the deny log before you make the policy stricter. Compare declared policy against effective policy on a schedule, because the two drift. Instrument every tool call with the tool name, the target, the decision and the policy revision in force, or you will never be able to explain a deny later. Treat a near-zero deny rate in the first week as evidence your boundary is too loose rather than evidence your agent is well behaved. And keep a kill switch that does not require the agent to cooperate, because the day you need it is the day it is not cooperating.
📌 Frequently Asked Questions
What is Microsoft Execution Containers (MXC)?
A policy-driven execution layer for untrusted or dynamically generated workloads, generally available since October 7, 2026. Developers and IT administrators declare the resources an agent may use and MXC uses an appropriate container to enforce those policies at runtime.
What can MXC contain?
Model-generated output, plugins, tools, an agent harness, or the entire agent. Microsoft describes the goal as limiting what the agent workload can access, which caps the impact when something goes wrong.
How is this different from just running the agent in a container?
A container tells you where the workload runs. MXC is about what it may reach and who decides. The enforcement decision lives outside the agent, and the agent cannot be its own security authority - that is the design principle Microsoft states explicitly.
Do I still need secret management?
Yes. Containment limits reach, not spending power. A contained agent holding a live API key can still consume that key's quota. Keep credentials out of the contained workload's filesystem and prefer short-lived, narrowly scoped tokens.
What is the most common deployment mistake?
Declaring a policy and assuming it is enforced. Compare declared policy with effective policy on a schedule, log the policy revision on every tool call, and treat a suspiciously low deny rate in week one as a signal the boundary is too loose.
🔧 Recommended Tools
📚 Sources
- Windows Developer Blog: Microsoft Execution Containers - Policy-driven containment for AI agents (October 7, 2026)
- Windows Developer Blog: Build 2026 - furthering Windows as the trusted platform for development
- Petri: Microsoft Makes Execution Containers Available for AI Agents
- C# Corner: Microsoft Execution Containers Give AI Agents a Managed Security Boundary