微软 Execution Containers 正式可用:Agent 不能做自己的安全权威
💡 工具推荐:YAML 转 JSON、文本差异对比、JSON 格式化、正则测试器
微软于 2026 年 10 月 7 日把 Microsoft Execution Containers(MXC)推向正式可用。微软公告里有一句话值得读两遍:Agent 不能做自己的安全权威。整件事的意思就在这一句里。MXC 是一个策略驱动的执行层,面向你没有写、也无法完全预测的代码——模型输出、插件、工具、Agent 的 harness,乃至整个 Agent。开发者和管理员声明可以使用哪些文件与网络目的地,Windows 再挑选合适的容器在运行时执行这些声明。
边界必须放在你不信任的那个工作负载之外
MXC 到底是什么
MXC 是一个面向不可信或动态生成负载的策略驱动执行层。在 Agent 场景里,你可以选择「contained」的范围:模型生成的输出、插件、工具、Agent harness,或者整个 Agent。这个范围由你来定。微软明确说,目标是限制 Agent 工作负载能访问什么,也就是在出事时把影响范围封顶,而不是假装不会出事。它现在是正式可用(GA)而不是预览,所以设计上的假设变了:这是要在生产里配置的东西,不是拿来试试的东西。
# 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 限制 Agent 能访问什么、能做什么;Identity 把 Agent 的行为与人的行为区分开,Windows 很快就会让 Microsoft Entra 来做这件事——这点很关键,因为一个继承了人类凭据的 Agent,正是你读到的审计事故里一半的根因;Manageability 给组织提供治理访问与监控活动的工具,把 Microsoft Agent 365 的管控扩展到设备上的本地 Agent,让 IT 能管理 MXC 容器、下发策略、监视 Agent 的行为。只有隔离没有监控,那就是一堵没有摄像头的墙。
# 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.
策略在运行时执行,而不是在评审时
为什么 Agent 不能自己监管自己
如果由 Agent 来决定自己的动作是否被允许,那你拥有的不是控制,而是建议。被测对象恰恰就是被信任程度不明的这个负载,它不能同时当裁判。所以真正有用的工程问题不是「把 Agent 放进容器」,而是「强制执行的决定发生在哪里,这个负载能不能碰到它」。MXC 的答案是:把决定搬进操作系统,放在 Agent 代码路径之外。任何 Agent 能修改、能绕过、能讨价还价的策略,都只是装饰。检验方法很简单:在最糟糕的那一天,模型的输出能不能改掉管它的那条规则?
# 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
比提示词活得更久的策略
提示词天天在变,策略应该有意地变、经过评审地变。把边界写成声明式策略而不是写在提示词里的指令,才能让它熬过一次模型替换、一次框架升级、一次新工具接入。实际的形状就是一个 mxc-policy.yaml:读这些目录、写那些目录、只能访问这一个 API、默认拒绝其余、不派生子进程。它读起来像一份防火墙规则集,因为它本来就是。推论是:策略从此需要版本管理、需要评审、需要 diff——而 diff 恰恰是价值最大的地方。
# 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.
先声明策略,再拿真实工具调用去测
隔离解决不了什么
MXC 不会告诉你 Agent 挑的文件对不对,只告诉你它有没有权限。它也拦不住一次提示词注入——模型被说服去外泄一份它本来就有权访问的文档,这个调用在策略内,意图在策略外。它不替代密钥管理,因为一个被隔离、但手里拿着有效 API Key 的 Agent,照样能把你的额度烧掉。它治不好一个本来就过大的工具面。如果你把策略声明下去却从不验证它真的被执行了,它也帮不了你——这是所有控制系统里最常见的失败模式。
# 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.
不会把你半夜叫起来的上线顺序
先在一个团队的一个 Agent 上、用低流量开始,并且在收紧策略之前先读拒绝日志。定期比对「声明策略」与「生效策略」,因为这两者会漂移。给每一次工具调用都打上工具名、目标、决定、以及当时生效的策略版本,否则将来你永远解释不清某一次拒绝。如果第一周拒绝率几乎为零,把它当作「边界太松」的证据,而不是「Agent 很乖」的证据。另外留一个不需要 Agent 配合就能生效的开关,因为你需要它的那一天,恰恰就是它不配合的那一天。
📌 常见问题 FAQ
Microsoft Execution Containers(MXC)是什么?
它是面向不可信或动态生成负载的策略驱动执行层,自 2026 年 10 月 7 日起正式可用。开发者与 IT 管理员声明 Agent 可以使用的资源,MXC 用合适的容器在运行时执行这些策略。
MXC 能隔离哪些东西?
模型生成的输出、插件、工具、Agent harness,或者整个 Agent。微软把目标描述为限制 Agent 工作负载能访问什么,从而在出错时把影响封顶。
这和「直接把 Agent 跑在容器里」有什么区别?
容器回答的是「负载跑在哪里」,MXC 回答的是「它能碰到什么、谁来做决定」。强制执行的决定放在 Agent 之外,Agent 不能做自己的安全权威——这是微软明确写出的设计原则。
还需要密钥管理吗?
需要。隔离限制的是可达范围,不是消费能力。一个被隔离但持有有效 API Key 的 Agent 依然能消耗该 Key 的额度。把凭据排除在被隔离负载的文件系统之外,优先使用短时效、窄范围的令牌。
最常见的部署错误是什么?
把策略声明下去就假定它会生效。要定期比对声明策略与生效策略,在每次工具调用上记录策略版本,并把第一周异常低的拒绝率当作边界太松的信号。
📚 参考资料
- 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