Skip to content

Browse catalog

Search catalog

[READY] Type a title, tag, or description.

Harness

MXC Learning mode drafts your agent's sandbox - on Windows only

AUTHOR
Bartłomiej Krupa
PUBLISHED
2026.10.14
READ_TIME
8 min

MXC Learning mode records every file, network, and capability access your coding agent was denied, then hands you a JSON list you can turn into a least-privilege sandbox policy - one that grants only the access the task needs. It ships in Microsoft Execution Containers (MXC) 1.0, released 2026-10-07 and already used by GitHub Copilot and OpenAI Codex. The catch: the denial report works only on Windows, and the obvious shortcut, wxc-exec --audit, switches containment off while it records.

Read on if you run a coding agent on Windows, or build a harness that has to sandbox agents on Windows, macOS, and Linux from one config. On a Mac with Claude Code only? Jump to what MXC does not contain. Claude Code doesn’t support MXC yet.

What MXC is

MXC (Microsoft Execution Containers) is an MIT-licensed SDK for Rust, .NET, and Node that takes one JSON policy - which files, network destinations, processes, and UI the workload may touch - and enforces it with the operating system’s own sandbox. The policy lives outside the agent, so the agent, its generated code, or a plugin “cannot grant itself additional access.”

MXC is not a new isolation technology. It’s one API in front of the ones each OS already has:

  • AppContainer - Windows’ built-in process sandbox.
  • Seatbelt - macOS’s kernel sandbox, the same one Claude Code’s /sandbox uses on a Mac.
  • Bubblewrap - a Linux tool that runs a process in an isolated view of the system that sees only the folders you hand it; also what /sandbox uses on Linux.
PlatformDefault backendOther backends
Windows 11 (x64, ARM64)processcontainer (AppContainer)wslc, isolation_session; experimental: windows_sandbox, microvm, hyperlight
Linux (x64, ARM64)bubblewraplxc, microvm, hyperlight
macOS (ARM64, x64)seatbeltnone

The session container (isolation_session) is Windows-only: it runs the agent under a separate Windows account with its own desktop, clipboard, and input. Microsoft pitches it for long-running agents that need a desktop or stronger separation from the person at the keyboard.

The policy: five areas

AreaControls
ContainmentWhich backend runs the workload
ProcessCommand, arguments, working directory, environment
File systemreadwritePaths, readonlyPaths, deniedPaths
NetworkInbound and outbound rules, host loopback
User interfaceDesktop, clipboard, display access

The smallest useful request, from the MXC README:

import { spawn, type ContainerRequest } from '@microsoft/mxc-sdk/v1';

const request: ContainerRequest = {
  command: 'node -e "console.log(\'hello from container\')"',
  network: { egress: { default: 'deny' } },
  timeoutMs: 30_000,
};

const child = await spawn(request);

Everything is deny-by-default. Touch something the policy doesn’t grant and the OS returns a plain “Access is denied”, and the tool fails. Microsoft’s own post names the problem: writing a least-privilege policy is hard when you don’t yet know every resource the workload needs. An agent’s workload changes with every task.

Three modes, and only two contain

MXC’s answer is to record what was blocked. It has three modes:

ModeUngranted accessActivity reportPlatforms
EnforcementBlockedNoAll
LearningBlocked and recordedYesWindows ProcessContainer only
PermissiveAllowed and recordedYesWindows ProcessContainer only

Two traps in that table.

Learning is Windows-only. MXC’s docs say the learning-mode capabilities “are Windows-only” and apply to the AppContainer-based backends; “on other platforms the capability strings are ignored.” On a Mac or Linux box you get enforcement and no report.

--audit is Permissive, not Learning. The README’s warning is blunt: --audit “turns off all sandbox security for the workload being analyzed. Never use it to run untrusted code.” It’s built for a developer bringing up their own trusted tool. A coding agent that may have read a prompt-injected README is not a trusted tool.

Draft a policy from the denial log (Windows)

Use deny-and-record: the agent behaves exactly as it will in production, and you get a list of what it reached for.

  1. Start from a tight policy. Grant the repository read-write, deny outbound network, and turn on captureDenials in block mode. Field names below come from the Node V1 types and the official run-with-logging-access-denied sample:

    import { run, type ContainerRequest } from '@microsoft/mxc-sdk/v1';
    
    const repo = 'C:\\src\\my-repo';
    
    const request: ContainerRequest = {
      command: 'npm test',
      containment: {
        type: 'processcontainer',
        config: {
          captureDenials: { mode: 'block', outputPath: 'C:\\logs\\denials.json' },
        },
      },
      filesystem: { readwritePaths: [repo] },
      workingDirectory: repo,
      network: { egress: { default: 'deny' } },
      timeoutMs: 600_000,
    };
    
    const result = await run(request);
    console.log(result.outputMetadata?.captureDenials);

    C:\logs must already exist. MXC inserts a per-run ID into the filename (denials.<run-id>.json), so read the real path from outputMetadata.captureDenials.outputPath. You may also see processContainer.learningMode: true in the docs: it turns on the same deny-and-record mode, while captureDenials is the switch that also collects the denials into this JSON report. Use captureDenials.

  2. Run the agent’s real task, not a toy command. The report only lists what the run actually touched.

  3. Read the report. Each entry is one blocked (resource, accessType) pair, already de-duplicated:

    {
      "denials": [
        {
          "resource": "C:\\Users\\test\\secret.txt",
          "resourceType": "file",
          "accessType": "read",
          "pid": 1234,
          "filetime": "132847890123456789"
        },
        {
          "resource": "internetClient",
          "resourceType": "capability",
          "accessType": "unknown",
          "pid": 1234,
          "filetime": "132847890123512345"
        }
      ],
      "summary": { "exitCode": 0, "totalDenials": 2, "deniedResourcesTruncated": false }
    }
  4. Grant only what the task needs. A toolchain cache read goes into readonlyPaths. A home-directory secret stays denied - that denial is the sandbox doing its job, not a gap. A capability entry such as internetClient names a Windows AppContainer permission the workload asked for; grant it only if the task really needs it.

  5. Re-run until the denials are only the ones you meant. If deniedResourcesTruncated is true, the run hit the cap (10,000 unique denials or 1,000,000 trace events) and the list is incomplete.

A caveat: I haven’t run this on a Windows box. The code is assembled from MXC’s Node types and its official sample, so check it against the sample first.

What MXC does not contain

MXC wraps the processes your harness launches through it. Anything the harness does in its own process is outside the box.

GitHub Copilot is the clearest worked example. With sandboxing on (/sandbox in the Copilot CLI), shell commands, local MCP servers, and language servers run inside MXC: the BaseContainer tier of ProcessContainer on Windows, Seatbelt on macOS, Bubblewrap on Linux. Built-in file tools run inside Copilot itself, where “the agent harness checks their requests against the effective policy, but those checks aren’t OS-enforced.” Remote MCP servers are outside the local sandbox too.

That’s the same shape as Claude Code’s /sandbox, which wraps Bash and its children but not Read, Edit, or MCP. The Claude Code sandboxing guide covers that gap and the isolation ladder above it.

AgentMXC status (2026-10-07)
GitHub CopilotSupports it
OpenAI CodexSupports it
Replit, OpenClaw, LM Studio, UnslothSupport it
Claude Code“Will be releasing support”
Hermes Agent, Manus, Perplexity, Raycast“Will be releasing support”

Known issues at 1.0

A week after the 1.0 release, the Windows ProcessContainer still breaks ordinary developer tools:

SymptomCauseIssue
Node fs.realpathSync.native fails with EPERM; git loses its working directoryGetFinalPathNameByHandleW(VOLUME_NAME_DOS) returns ERROR_ACCESS_DENIED (5) inside the container, whatever the file-system policy#1464
cd into a read-only grant fails with ERROR_ACCESS_DENIEDDirectory opens with FILE_TRAVERSE are denied on read-only paths#1467

The Hacker News thread (228 points) is skeptical in the same direction. One commenter who tried it: “it’s not a 1.0 release. This is more like an early tech preview.” Another: some Windows backends “cause many exes to straight up fail during startup (powershell for instance).” Others ask why they’d use the wrapper over Bubblewrap directly - a fair question if you only ship on Linux.

When MXC is worth it

  • You build a harness that runs on Windows, macOS, and Linux. One policy schema and one SDK beat three hand-written sandbox configs. That’s the actual pitch.
  • You run agents on Windows. It’s the only platform where MXC gives you a denial report, and the only one with a session container that keeps the agent off your desktop.

Not worth it yet if you only use Claude Code on a Mac or Linux: /sandbox already uses Seatbelt or Bubblewrap. Climb the sandbox ladder for anything it doesn’t cover.

Next step on Windows: clone microsoft/mxc, run samples/run-with-logging-access-denied/node, and confirm your Windows build supports denial capture before you point it at an agent.

FAQ

Does MXC Learning mode work on macOS or Linux?
No. MXC's learning-mode capabilities apply only to the Windows AppContainer-based backends (ProcessContainer). On macOS (Seatbelt) and Linux (Bubblewrap) the capability strings are ignored, so you get enforcement but no denial report.
Is wxc-exec --audit safe to run on an untrusted coding agent?
No. The MXC README warns that --audit turns off all sandbox security for the workload while it records accesses. It is Permissive mode. For an agent you don't trust, use captureDenials with mode 'block' (or processContainer.learningMode: true), which keeps every ungranted access denied while logging it.
Does Claude Code support Microsoft Execution Containers?
Not as of MXC 1.0 (2026-10-07). Microsoft lists GitHub Copilot, OpenAI Codex, Replit, OpenClaw, LM Studio, and Unsloth as supporting MXC today, and Anthropic Claude Code among agents that 'will be releasing support'.

Sources

  1. Microsoft Execution Containers: Policy-driven containment for AI agentsMicrosoft
  2. MXC SDK v1.0.0 release notesMicrosoft
  3. MXC READMEMicrosoft
  4. MXC learning-mode capabilities (logging access denied)Microsoft
  5. MXC Node SDK V1 typesMicrosoft
  6. Bringing local models and sandboxed tools to Windows and GitHub CopilotMicrosoft
  7. mxc #1464: GetFinalPathNameByHandleW(VOLUME_NAME_DOS) always failsGitHub
  8. mxc #1467: SetCurrentDirectory into a read-only path failsGitHub
  9. Mxc: Microsoft Execution Containers version 1.0.0Hacker News