Special Topic · Inside OpenAI Codex

Windows: restricted token, firewall filter, and two dedicated system users

Windows has no seatbelt and no bubblewrap. Codex stacks a restricted token, a firewall filter, and two dedicated system users into a sandbox — and why AppContainer does not fit this permission model

THE QUESTION THIS PAGE ANSWERS

ANSWER FIRST

What is the key idea behind “Windows: restricted token, firewall filter, and two dedicated system users”?

Windows has no seatbelt and no bubblewrap. Codex stacks a restricted token, a firewall filter, and two dedicated system users into a sandbox — and why AppContainer does not fit this permission model

DECISION RULE

Follow the handoffs, not the demo. A system becomes dependable at the boundaries between model, tools, state, permissions, and people. Read each handoff as a place where you can observe, test, and recover.

TRY NEXT

Name the input, owner, approval, and recovery action for one automated step.

WATCH FOR

A successful run that cannot explain what happened or be safely repeated.

Course goalAfter this lesson you can explain three things. Why Windows can only lock resources by identity. Why those three restricted-token flags can hold writes but not reads or the network. Why two dedicated system users exist, and why AppContainer was set aside.
Try it first · One request through three gates
Swap actions and tiers, see which gate stops the request
Action
Tier
Watch Elevated block a read at the identity gate. Drop to RestrictedToken and the same read walks through.
This request
Read C:\Users\you\.ssh\id_rsa
Current identity
CodexSandboxOffline
Gate 1 · Restricted tokenStandby
Three flags cut the token. Writes must pass a cross-check; reads at this tier still follow the current user.
Gate 2 · Dedicated system userStandby
Only Elevated logs in as CodexSandboxOffline or Online, and hollows out directories like .ssh via the account ACL.
Gate 3 · Firewall filterStandby
Persistent WFP is installed only for the offline account. ICMP, DNS, and SMB are filtered in the kernel; ordinary outbound goes to the outbound firewall.
Hit Play to watch this request walk the three gates.
Logic trail · each animation step maps to a source span
  1. Windows switch is off; the platform sandbox returns empty; no wrapper is wrapped latermanager.rs L62
  2. When a sandbox is needed, use its own exe plus a hidden flag as the wrapperwrapper.rs L20
  3. Three flags cut a restricted token: strip privileges, LUA, writes must pass a cross-checktoken.rs L480
  4. At the RestrictedToken tier, the read check does not look at capability SIDswindows.rs L109
  5. Elevated logs in with a dedicated account first, then cuts down from that tokenrunner_client.rs L348
  6. Two account names are hard-coded: Offline and Onlinesetup.rs L50
  7. When network policy is off or a proxy is used, pick the Offline identitysetup.rs L706
  8. Install persistent WFP filters only for the offline accountwfp.rs L75
  9. The user-profile root hollows out .ssh and similar directories by defaultsetup.rs L56
  10. With no backend, a read-only profile plus Never means unmatched commands must be Forbiddenexec_policy_windows_tests.rs L113
Hit Play to watch this request walk the three gates.
The token tier only locks writesRestrictedToken cuts a token from the current user. Reading a file outside the workspace, and sending traffic out, both walk through. To stop them you must switch to Elevated.
Only the identity gate hollows things out.ssh sits on the user-profile exclusion list. That ACL takes effect only after a dedicated account is logged in.
The network hangs on a SIDWFP is installed only for the offline account. The token tier has neither account, so the third gate does not exist.
Teaching sketch: paths and account names are course fixtures. Line numbers on the logic trail match openai/codex commit 4f39251a01.
Idea 1 · No process view, so lock resources by identity
What problem it solves

A teammate runs Codex on a Mac; the agent touches an SSH private-key path in the user profile; Seatbelt stops it at once, and the error says Operation not permitted. Put the same read on Windows and the error becomes Access is denied. Switch to a machine that never turned on the Windows sandbox, and the command may never reach an ACL — execpolicy already marks it Forbidden or Prompt.

Three machines, one intent, three failures. The next sentence the model sees is different, so the next step changes with it. If Windows pretends it has the same default sandbox as Unix, the model plans as if it is confined — while the command runs naked.

What the idea is

macOS limits which operations this process may do on which paths. Linux limits what this process can see and which syscalls it can make. Windows has no namespace and no seccomp. Codex asks a different question: which resources can this identity touch.

The token decides who you are. The RestrictedToken tier cuts from the current-user token; the Elevated tier logs in with a dedicated account first, then cuts from that token. Both ends land on the same flags: DISABLE_MAX_PRIVILEGE, LUA_TOKEN, WRITE_RESTRICTED. Privileges are thinned; a write must pass both the ordinary ACL and a restricting-SID cross-check.

At the RestrictedToken tier, reads still follow the current user. The source says so itself: a capability-SID deny-read ACE on a WRITE_RESTRICTED token does not join the read check, so read limits must go through Elevated; a naked run is refused outright.Source: codex-rs/windows-sandbox-rs/src/token.rs line 480;codex-rs/sandboxing/src/windows.rs lines 109–117

macOS Lock what the process can do SBPL text file-read rule denies Operation not permitted Linux Lock what the process can see bubblewrap view Path is not in the mounts No such file or directory Windows Lock what this identity can touch Token plus ACL Identity has no permission Access is denied
Teaching diagram: the same read, three isolation stacks lock different layers, and the failure semantics the model sees are not the same.
Why it lasts

What a subject can do, and who may touch an object, are two isolation primitives. Rewrite it in another language: Windows still has no bwrap to call. The question remains: do you have an identity, and what is that identity allowed to touch.

The wrap is the same family of self-invocation. Windows uses its own exe plus a hidden --run-as-windows-sandbox flag — the same idea as Linux rewriting arg0.Source: codex-rs/windows-sandbox-rs/src/wrapper.rs line 20

Idea 2 · One identity can carry only one network policy
What problem it solves

WFP is the Windows Filtering Platform, a kernel packet-filter framework. It and the firewall rules both match on SID. One SID can carry only one network policy. The same identity cannot mean “no network at all” and also “may use a proxy or go outbound.”

What the idea is

So two local users become two network identities: CodexSandboxOffline and CodexSandboxOnline. from_permissions picks Offline when a proxy is forced, or when network policy is off. The offline identity installs outbound blocks, a proxy-port allowlist, then 12 WFP rules covering ICMP, DNS 53, DNS-over-TLS 853, and SMB. The online identity does not install that block set.

Unix network isolation swaps the NIC view the process sees. WFP leaves the process on the host network stack; only certain traffic from this SID is blocked. The process can still see NICs, fail DNS, and connect to other ports.

Filters are identified by stable GUIDs, carry a persist flag, and survive reboot. Uninstall and crash do not tear them down automatically. The repo has no function that deletes the users or removes WFP. A WFP failure is written as non-fatal; a firewall failure fails the whole setup.Source: codex-rs/windows-sandbox-rs/src/setup.rs lines 50–51、lines 706–714;codex-rs/windows-sandbox-rs/src/wfp.rs lines 69–95

One SID, two network policies that fight The same account No network at all May use a proxy or go outbound Filters match by SID; two sets will not install Two accounts, two network policies CodexSandboxOffline 12 WFP rules plus outbound blocks Online Does not install that block set Outbound
Teaching diagram: two network-policy tiers need two identities.
Why it lasts

When access control is by identity, the number of identities must cover the number of policy combinations. Two network-policy tiers need two identities. It is the same as two badge cards for two buildings — independent of WFP as a concrete API.

Idea 3 · AppContainer does not fit, Elevated is too expensive, so default off
What problem it solves

Someone will ask why not AppContainer. Its default readable range is narrow; arbitrary-path reads require changing the host DACL. Codex needs the workspace readable, the platform root readable, then hollow-outs from a deny list. A restricted token plus ACL fits this permission model better. Search AppContainer under codex-rs/ and business code has zero hits. The comparison repo DeepSeek Harness writes the same judgment in plain text: AppContainer cannot do arbitrary-path reads.

For Elevated to also govern reads and the network, you must create accounts, pop UAC, and change the firewall and WFP. Enterprise policy may forbid creating local users. Setting the default to Disabled leaves that product friction for the first enable.

What the idea is

The enum itself writes the default as off. If windows.sandbox is unset and both legacy flags are absent, it falls back to Disabled. The legacy flags are already marked Removed.

codex-rs/protocol/src/config_types.rslines 297–302
pub enum WindowsSandboxLevel {
    #[default]
    Disabled,
    RestrictedToken,
    Elevated,
}
Source snapshot note: based on the local openai/codex repo; verified file codex-rs/protocol/src/config_types.rs, commit 4f39251a01, verified 2026-08-22. The code block keeps the original source; #[default] is pinned on Disabled.

After it is off, the platform sandbox is truly gone. get_platform_sandbox(false) returns empty on Windows; select_initial turns that into SandboxType::None. The command may still be stopped at the policy layer. A Windows test locks this in: with no backend, a read-only profile plus Never approval means unmatched cmd.exe /c dir must be Decision::Forbidden.Source: codex-rs/sandboxing/src/manager.rs lines 62–72、line 301;codex-rs/core/src/exec_policy_windows_tests.rs lines 113–130

AppContainer Default readable range is narrow Arbitrary paths need a host DACL change Does not fit this permission model The combo Token locks writes Dedicated account locks reads WFP filters the net by SID Needs UAC, needs a local user Default Disabled execpolicy as the backstop
Teaching diagram: the set that actually works is expensive, so default off first; the policy layer catches a naked run.
Three gates: one governs writes, one governs who you are, one governs which network door this identity may leave through.
Why it lasts

Isolation depth is tied to the install budget. If you only want to stop the model from accidentally editing the repo, a current-user restricted token is enough. To stop secrets being read and sent off this machine, you also need read limits and identity-based network filtering. Promise a wall you cannot build, and both the model and the user will decide against that wall.

When platforms are unequal, the public story must be written against the layer that is actually on. macOS has Seatbelt by default; Windows may default to Disabled. Users who hear “there is a sandbox” will think three machines share one wall.

Side-by-side · the same flags, three prices people will pay

DeepSeek Harness: the same flags, stop at write limits

DSH’s @deepseek-ai/dsh-sandbox-windows-acl uses the same CreateRestrictedToken flags: DISABLE_MAX_PRIVILEGE | LUA_TOKEN | WRITE_RESTRICTED. The README says reads, network, and process visibility are unrestricted; enforcement is marked partial. It does not create dedicated accounts and does not install WFP.

The design note writes the AppContainer rejection in stone: an AppContainer token has no ambient read, arbitrary-path reads must be pre-authorized, and that does not fit the harness read model. mxc was rejected because the OS-version floor is too new, and arbitrary-path reads still need a host DACL change. Codex Elevated puts reads and a network identity in with two accounts plus WFP; the cost is install friction and leftover state after uninstall. DSH traded for something that installs and runs, leaving reads and the network to other mechanisms.

Checked DSH token.ts / win32-abi.ts / README / design notes · 2026-08-22 · DSH · Sandbox: from seatbelt to the execution world

Claude refuses to run; Grok marks the platform unknown

Claude Code writes plainly that there is no sandbox on native Windows. When enterprise policy requires a sandbox and forbids unsandboxed commands, PowerShell refuses to run, with the copy sandboxing is not available on native Windows. It does not pretend there is a layer of isolation. Grok Build’s sandbox crate writes platforms as linux/landlock and macos/seatbelt, and marks the rest unknown. Search xai-grok-sandbox for AppContainer, RestrictedToken, CreateRestrictedToken — no matching implementation.

The answer splits into three tiers. Claude and Grok do no filesystem sandbox on Windows. DSH does write limits, installs cleanly, and leaves reads and the network to other mechanisms. Codex puts identity, ACL, WFP, and dedicated accounts all in — more friction, so it stays off by default.

Checked Claude PowerShellTool.tsx and Grok types.rs · 2026-08-22 · Grok · Five sandbox Profiles
Classroom Exercise
01

The same read — after you change tiers, where does it stick

Leave the demo action on reading outside the workspace, then drop the tier from Elevated to RestrictedToken. Write your prediction first: which gate allows, which gate vanishes, and whether the end is Access is denied or a walk-through. Then hit Play to check.

Advanced: switch the action to sending network. Why is the third gate skipped at RestrictedToken, and why does WFP light up only at Elevated?

Takeaway: Windows has no seatbelt and no bubblewrap; isolation can only lock resources by identity. Those three RestrictedToken flags govern writes, not reads or the network. To stop secrets and outbound traffic you also need dedicated accounts, ACLs, and WFP installed by SID. AppContainer does not fit this readable set, and Elevated wants UAC, so the default stays off; with no backend, execpolicy becomes Forbidden or Prompt.

The handoffs inside “Try it first · One request through three gates”

“A teammate runs Codex on a Mac;” shows that an Agent is not defined by the model alone. Each handoff between model, context, tools, state, permissions, and people affects both progress and recovery.

Write the state before adding capability

Starting from “Three machines, one intent, three failures.”, split the workflow into starting state, next action, tool result, state update, and stop condition. Debugging then means finding the first lost piece of information or authority instead of saying vaguely that the model “got worse”.

  • Windows switch is off; the platform sandbox returns empty; no wrapper is wrapped later manager.rs L62
  • When a sandbox is needed, use its own exe plus a hidden flag as the wrapper wrapper.rs L20
  • Three flags cut a restricted token: strip privileges, LUA, writes must pass a cross-check token.rs L480

A happy path is not reliability

Use “Advanced: switch the action to sending network.” to replay one successful and one failed run. Record the context, tool result, and owner at each turn; the workflow is maintainable when a second person can follow it without the original builder.

From “Try it first · One request through three gates” to “Idea 1 · No process view, so lock resources by identity”

“Try it first · One request through three gates” grounds the problem in “Swap actions and tiers, see which gate stops the request Play Step Reset Action Read workspace Read outside workspace Send network Edit a system directory Tier Off RestrictedToken Elevated Watch Elevated block…”. “Idea 1 · No process view, so lock resources by identity” then moves it toward “A teammate runs Codex on a Mac; the agent touches an SSH private-key path in the user profile; Seatbelt stops it at once, and the error says Operation not permitted. Put the same read on Windows and the error b…”. Together, they show that the lesson is not just a conclusion to remember, but a claim with conditions.

Carry the judgment into the next situation

When analyzing an Agent, trace state, action, tool result, and next step in order. Each handoff should explain where information came from, who confirmed it, and where failure stops.

  • “Try it first · One request through three gates”: Swap actions and tiers, see which gate stops the request Play Step Reset Action Read workspace Read outside workspace Send network Edit a system directory Tier Off RestrictedToken Elevated Watch Elevated block…
  • “Idea 1 · No process view, so lock resources by identity”: A teammate runs Codex on a Mac; the agent touches an SSH private-key path in the user profile; Seatbelt stops it at once, and the error says Operation not permitted. Put the same read on Windows and the error b…
  • “The closing point”: Elevated logs in with a dedicated account first, then cuts down from that token runner_client.rs L348

The final “The closing point” brings the discussion to “Elevated logs in with a dedicated account first, then cuts down from that token runner_client.rs L348”. The useful thing to carry forward is knowing which judgments must be revisited when input, scale, or risk changes.

Mark as learned Your reading progress updates automatically
← PreviousNext →

Keep reading

The next useful article in the thread.

ARTICLE DISCUSSION

Leave one useful thought here.

Keep the idea that clicked, the question that stayed open, or a small note for the next learner.

Discussing Windows: restricted token, firewall filter, and two dedicated system users Inside OpenAI Codex
3discussionsArticle discussion · synced with the Circle
View in the learning circle
AM
Asha MorganContent editor
INSIGHTField note

I turned one judgment from this article into a small experiment I could run today. Knowing what to observe next is more useful than simply remembering the conclusion.

ARTICLE DISCUSSION7 helpful
LH
Lin HarperIndie developer
INSIGHTInsight

After reading this, I first looked for the conditions behind the idea instead of copying the method into a project. That order made the later trade-offs much clearer.

ARTICLE DISCUSSION5 helpful
KM
Kiki MooreProduct operations
QUESTIONQuestion

When this judgment reaches real work, which constraint should be added first? I am curious which step matters most between reading and the first practical attempt.

ARTICLE DISCUSSION4 helpful