60 min read

AppContainer and LowBox Tokens: Windows's Capability Sandbox

How a single bit in Windows's access token, two new SID alphabets, and a per-package namespace partition let the kernel give two co-tenanted apps opposite verdicts.

Permalink

1. Two Calculators

Open calc.exe on a stock Windows 11 25H2 installation. It is the Microsoft Store calculator, the UWP one, the one Windows ships in the default Start menu. Now download the legacy win32calc.exe from a Windows 7 image and run it side by side. Same user. Same machine. Same disk, same DACLs on every file in your profile. The Mandatory Integrity Control label on %USERPROFILE%\.ssh\id_ed25519 is the default Medium for both processes' access checks.

Yet win32calc.exe can read the SSH private key, and calc.exe cannot. If you open both processes in Sysinternals Process Explorer and compare the Security tab side by side, every field that the classic Windows NT token model exposes looks identical. User SID: identical. Logon ID: identical. Primary group: identical. Privileges: identical. Even the integrity level, by the read path, looks the same on the user's profile files.

The difference is one bit. In the kernel's _TOKEN structure, the TOKEN_LOWBOX flag (SDK constant value 0x4000, the 15th bit of the TokenFlags word) is set on the UWP calc.exe token and clear on win32calc.exe [1]. Microsoft's documentation calls the resulting token an AppContainer token; the kernel call that creates it preserved the older marketing name. "AppContainer was originally named LowBox (prior to the release of Windows 8). That legacy name can be seen in API names such as NtCreateLowBoxToken" [2].

"AppContainer was originally named LowBox (prior to the release of Windows 8). That legacy name can be seen in API names such as NtCreateLowBoxToken." -- Microsoft Learn

AppContainer

The public-API name for a kernel-enforced per-application sandbox introduced in Windows 8 [2]. An AppContainer process runs under a LowBox token, a special access token whose LowBoxToken flag, package SID, capability SIDs, and per-instance number cause the Security Reference Monitor to apply additional access-check rules beyond the classic user-and-groups DACL walk. The kernel-internal name LowBox is preserved in NtCreateLowBoxToken and several adjacent symbol names [3].

If you read the eight sub-authorities of the Calculator's package SID -- something like S-1-15-2-466767348-3739614953-2700836392-... (the trailing five sub-authorities are elided here) -- you are reading a deterministic SHA-256 hash of the package family name, sliced into eight 4-byte 32-bit sub-authorities [4] [1]. Every Windows 11 machine in the world derives the same SID for Microsoft.WindowsCalculator_8wekyb3d8bbwe, and DACLs on the per-package data directories name precisely that SID. Section 5 will walk this in detail; for now, notice that the SID alphabet starts with S-1-15-2, not the familiar S-1-5-21 of user SIDs. Microsoft introduced two new SID prefixes in Windows 8: S-1-15-2-* for packages and S-1-15-3-* for capabilities. Both live in identifier authority 15, the App Package Authority [5].

Ctrl + scroll to zoom
Two calc.exe processes, opposite verdicts. The same user invokes the same kind of object access; one process succeeds and one fails because the LowBox flag triggers the per-app principal check path.

The question that opens this article is the same one Windows NT 3.1 could not ask in July 1993: two processes, same user, same DACLs, how does the kernel give them different verdicts? For nineteen years it could not. The answer Microsoft shipped on October 26, 2012 is the LowBox token, and we will trace one coherent primitive from its Vista-era ancestors through the four production deployments that exercise it on every Windows 11 machine in 2026. We will end with the exploit history that shaped its current hardening. The story starts on January 30, 2007, with a single browser, a single bit, and a structural defect Microsoft spent the next fourteen years repairing.

2. The Internet Explorer 7 Protected Mode Era

By the time Windows Vista went generally available on January 30, 2007 [6], a large majority of home Windows installs ran day-to-day under administrator accounts. The Wikipedia summary of User Account Control captures the pre-Vista status quo plainly: in Windows 1.0 through Windows 9x, "all applications had privileges equivalent to the operating system" [7]. One browser exploit equalled total compromise of the user profile, and Internet Explorer 6 from 2001 was the single largest pathway between hostile content and the desktop.

Vista's response had two halves. The first was User Account Control, the split-token model that asks the user to consent before promoting a Medium-integrity process to High. The second was Mandatory Integrity Control (MIC), the labelling primitive UAC depended on. MIC defined four integrity levels with their own SIDs: Low (S-1-16-4096), Medium (S-1-16-8192), High (S-1-16-12288), and System (S-1-16-16384) [8]. The Security Reference Monitor checks the label before the DACL; a label deny short-circuits the access check.

Mandatory Integrity Control (MIC)

A Windows Vista security mechanism that adds an integrity level to every process and every securable object [9]. Levels are System, High, Medium, and Low; objects carry a SYSTEM_MANDATORY_LABEL_ACE in their SACL declaring a minimum integrity level for access. By default the system creates every object with an access mask of SYSTEM_MANDATORY_LABEL_NO_WRITE_UP, which prevents lower-IL writers from modifying higher-IL objects but does not block reads.

The four MIC integrity-level SIDs are spaced at 0x1000-unit increments, the consecutive SECURITY_MANDATORY_*_RID constants in winnt.h: Low S-1-16-4096 (0x1000), Medium S-1-16-8192 (0x2000), High S-1-16-12288 (0x3000), System S-1-16-16384 (0x4000) [8]. They are in identifier authority 16, the Mandatory Label Authority.

Internet Explorer 7, which had shipped on October 18, 2006 [10], became MIC's first marquee consumer. IE 7's Protected Mode launched the renderer at Low integrity, where it could not write to %USERPROFILE% (Medium IL by default) or to HKLM. A separate Medium-IL broker process named ieuser.exe accepted COM requests from the renderer and performed privileged work on its behalf -- saving downloads, writing to non-Low locations -- only for operations the policy allowed. The renderer's private workspace lived at %USERPROFILE%\AppData\LocalLow\ and the corresponding Low-IL temporary internet files [11]. Marc Silbey and Peter Brundrett documented the design on MSDN. The MSDN article is preserved at a third-party mirror today; the original Microsoft path retired with the IE developer area.

The structural pattern was complete. A sandboxed worker process and a higher-privilege broker that re-elevates only the operations the policy permits is the topology of every later Windows-side capability sandbox. The same broker / target pattern reappears under several names: RuntimeBroker.exe for UWP, AppInfo for UAC consent prompts, PrintWorkflowUserSvc for print, and the WebAuthn and voice-activation brokers for those WinRT capabilities. Each is structurally ieuser.exe for a different resource. AppContainer's RuntimeBroker.exe is structurally the same idea as ieuser.exe. AppInfo (the UAC consent broker), the Print broker, the WebAuthn broker, and the voice-activation broker all share the lineage. Chromium's own broker / target sandbox, which we will meet in §3, was published less than two years later on the same conceptual base.

Ctrl + scroll to zoom
IE 7 Protected Mode topology, January 2007. The renderer runs at Low IL with a private Low-IL workspace; the Medium-IL ieuser broker re-elevates whitelisted operations on its behalf. This is the broker / target pattern AppContainer later generalised.

So far so good. But Protected Mode had three structural defects, and each one mapped one-to-one to a specific Windows 8 fix five years later.

Defect one: read-up was not blocked by default. The default mandatory-label ACE was SYSTEM_MANDATORY_LABEL_NO_WRITE_UP. A Low-IL process could not write to Medium-IL objects, but it could read them. The Microsoft Learn page on MIC is explicit: "the system creates every object with an access mask of SYSTEM_MANDATORY_LABEL_NO_WRITE_UP" [9]. Unless the object explicitly carried a NO_READ_UP mandatory ACE -- which %USERPROFILE%\.ssh\id_ed25519 did not -- a compromised Low-IL IE could read the user's SSH keys, browser passwords, OAuth refresh tokens, and any other Medium-IL secret. The Chromium sandbox FAQ flags the same observation: Vista's integrity levels were the only user-mode separation primitive available, and Chromium built a layered user-mode sandbox on top precisely because Vista's separation was insufficient [12].

Defect two: identity was shared across instances. Two Low-IL IE renderers ran with the same Low-IL SID and the same user SID. They could open handles to each other's named objects, shared memory sections, and process tokens. Integrity level is an axis; it is not a per-instance principal.

Defect three: network access was unconstrained. A Low-IL process could open any socket to any host. The Vista firewall was the freshly-introduced Windows Filtering Platform, but WFP had no notion of "which app is this" at all. As James Forshaw later put it on the Project Zero blog, "Prior to XP SP2 Windows didn't have a built-in firewall... While XP SP2 introduced the built-in firewall, the basis for the one used in modern versions of Windows was introduced in Vista as the Windows Filtering Platform (WFP)" [13]. WFP's per-application-package callout came years later, and the corresponding condition value FWPM_CONDITION_ALE_PACKAGE_ID did not exist in 2007.

Each defect became a specific Windows 8 mechanism. Defect one became the per-package namespace redirect plus the LowBox flag's NO_READ_UP-by-construction effect on cross-package reads. Defect two became the AppContainerNumber per-instance key. Defect three became the WFP capability gate. Microsoft and Google looked at the same Vista primitives and reached opposite conclusions. Google built a user-mode sandbox on top of NT. Microsoft built a per-app principal inside the NT token. The next two sections walk both branches.

3. Same Idea, Four Directions

Between January 2007 and October 2012, four different teams reached the same conclusion from four different starting points: the kernel needs a per-application principal, not just a per-user one. They built it in four different places.

Chromium sandbox, December 2008. When Chrome 1.0 shipped on Windows in December 2008, it carried a layered user-mode sandbox: a broker process plus a target process, a restricted token derived from the user's token, a job object that limited the target's syscall surface, and (on Vista and later) the Low integrity level on the target. The Chromium sandbox design document spells out the rule that defined the choice. "Do not re-invent the wheel: It is tempting to extend the OS kernel with a better security model. Don't. Let the operating system apply its security to the objects it controls" [14]. The reasoning continues in the FAQ. "the sandbox cannot provide any protection against bugs in system components such as the kernel it is running on" [12]. The Chromium design was a user-mode-only sandbox, layered on top of NT primitives that already existed.

Google Native Client, 2009. Bennet Yee and co-authors at Google published Native Client: A Sandbox for Portable, Untrusted x86 Native Code at IEEE S&P 2009 [15]. NaCl declared its capabilities at launch and structurally inverted the question: rather than retrofit a sandbox onto an application, run untrusted code only with capabilities the host has explicitly granted. The Wikipedia retrospective records NaCl's eventual replacement by WebAssembly [16], but the design idea -- capability-declared-at-launch -- prefigured what Microsoft would call SECURITY_CAPABILITIES.Capabilities[] three years later.

Apple iOS application sandbox, 2007 onward. iPhone OS 1.0 (June 29, 2007) shipped with a kernel-side TrustedBSD-derived MAC sandbox that confined Apple's own built-in apps [17]. The developer-facing surface -- third-party apps, Bundle IDs, Team IDs, and the entitlements dictionary -- arrived with iPhone OS 2.0 in July 2008 alongside the public App Store [17]. From 2008 onward the per-app principal had two halves: a Bundle ID (a string the developer picks, structurally like a Windows Package Family Name) and a Team ID (the signer). Each app's profile lived at Containers/Data/Application/<bundle-uuid>/, structurally similar to Windows's later %LOCALAPPDATA%\Packages\<PFN>\. The capability set was an entitlements dictionary signed into the app bundle, structurally similar to Windows's later <Capabilities> element.

Android per-app UID, September 23, 2008. When Android 1.0 shipped on the T-Mobile G1 on September 23, 2008 [18], it carried the most parsimonious solution: each app got its own UNIX UID. Classical Unix discretionary access control did the rest. Where Windows extended the SID alphabet, Android extended the UID allocation policy. The Android Application Sandbox page records the additional MAC layers Android added in later releases -- SELinux from Android 5.0 onward, seccomp-bpf from Android 8.0 onward, and per-physical-user partitions [19]. The kernel principal stayed a Unix UID.

Crispin Cowan, Jan 17, 2008. Between the Vista release and the eventual Windows 8 ship, the person who would write Microsoft's answer arrived on the security team. Crispin Cowan, the StackGuard co-author whose 1998 USENIX paper coined the term stack canary [20], joined the Microsoft Windows security team in January 2008. ZDNet's coverage of the hire reads: "Crispin Cowan, the Linux security expert behind StackGard [sic], the Immunix Linux distro and AppArmor, has joined the Windows security team... Crispin will join the team that worked on User Account Control" [21]. Cowan's later USENIX Security 2013 keynote Windows 8 Security: Supporting User Confidence credits him with the AppContainer design [22], and his University of Waterloo speaker page makes the attribution explicit: "From 2008 to 2017, Dr. Cowan was with Microsoft, where he designed the App Container sandbox that is used by the Edge and Chrome web browsers, Microsoft Office, and Windows 10 to contain Universal Windows Apps" [23].

The four mechanisms compare like this:

YearOperating systemPrincipal nameHow it is namedHow it is enforced
2007iOSBundle ID + Team ID (from 2008)Developer string + signerMandatory per-app MAC + entitlements
2008Chromium on Windows(none, user UID only)User SID + restricted tokenUser-mode broker + job object + IL
2008AndroidPer-app UNIX UIDUID allocated at installClassical Unix DAC + SELinux + seccomp
2012Windows 8Package SID + Capability SIDsDeterministic SHA-2 of monikerKernel access token + WFP + Object Manager
The name LowBox is itself a vestige of Microsoft's internal marketing process. The Win32 surface chose AppContainer in time for Windows 8's general availability; the kernel surface had already shipped under the older name. Microsoft Learn confirms the lineage in plain prose [2], and the syscall NtCreateLowBoxToken preserves it.

Microsoft had a choice: build a user-mode policy daemon like Apple, extend the user-keyed principal like Android, or keep everything in user mode like Chromium. The team chose the fourth option and extended the kernel access token. The next section walks how, year by year, that decision matured.

4. The Evolution, Generation by Generation

The Windows 8 ship on October 26, 2012 [24] [25] was not the end of the story. It was the start of a six-generation refinement that continues into 2026 Windows 11 25H2. The seven generations look like this on a timeline.

Ctrl + scroll to zoom
Seven generations of Windows per-application sandbox primitives, 1993 through 2026. Generation 0 is the classic NT user-token foil. Generations 1 through 6 are additive: a 2026 Edge browser inside Windows Sandbox exercises all of them at once.

4.1 Generation 0: The classic NT user-token model (1993)

Dave Cutler's Windows NT 3.1 shipped in July 1993 with a security model that is still the foundation in 2026. Every process has an access token. The token carries User, Groups[], Privileges[], and a DefaultDacl. Every securable object has a security descriptor with a DACL. SeAccessCheck walks the DACL access control entry by access control entry against the caller's user and group SIDs. Identity equals authority: if process A and process B both run as Alice, they are the same principal to the kernel. Whatever Alice can do, both of them can do. Chapter 7 of the seventh-edition Windows Internals [26] gives the canonical post-LowBox reference for this data structure.

This model has no answer to the single-user, multi-application threat. A user's text editor and a user's browser are indistinguishable principals. Bridge: the next generation tried to fix that by adding an axis, not a principal.

4.2 Generation 1: IE 7 Protected Mode plus MIC (Vista, 2007)

We already walked the mechanism in §2. Mandatory Integrity Control shipped with Vista's general availability on January 30, 2007 [6] [8]. Internet Explorer 7's Protected Mode launched its renderer at Low integrity with a Medium-IL ieuser.exe broker [7] [11]. The Wikipedia article on MIC names IE 7 as the marquee consumer: "Internet Explorer 7 introduces a MIC-based 'Protected Mode' setting" [8]. Bridge: integrity level is an axis, not a principal. Two Low-IL processes share identity.

4.3 Generation 2: The Chromium broker / target sandbox (Chrome, 2008)

The parallel path Microsoft did not take. Chromium's design document calls the architecture explicitly: "The Windows sandbox is a user-mode only sandbox" [14]. The two-process structure is named: "The minimal sandbox configuration has two processes: one that is a privileged controller known as the broker, and one or more sandboxed processes known as the target" [14]. The FAQ adds the integrity-level note: the sandbox "uses integrity levels" on Vista and later, and the only Vista-era application the FAQ knows about that used them was Internet Explorer 7 [12]. Bridge: who is this app? remains unanswered in any user-mode-only design.

"Do not re-invent the wheel: It is tempting to extend the OS kernel with a better security model. Don't. Let the operating system apply its security to the objects it controls." -- Chromium sandbox design document [14]

The pull quote is the most interesting sentence in the article so far, because Microsoft -- which was the operating system vendor -- did exactly the opposite four years later, and shipped AppContainer the same year (2012) Chrome 22 hit the desktop with its user-mode-only sandbox. The two browsers' modern descendants now run both designs simultaneously, but we are getting ahead of ourselves.

4.4 Generation 3: AppContainer / LowBox token (Windows 8, October 26, 2012)

This is the keystone. Microsoft made three structural extensions to the NT access-token model.

First, two new SID alphabets. The App Package Authority (identifier authority 15) carries Package SIDs at S-1-15-2-* and Capability SIDs at S-1-15-3-* [5]. A Package SID is a deterministic SHA-2-derived identifier for a specific package; a Capability SID names a permission the package declared in its manifest. Microsoft's DeriveAppContainerSidFromAppContainerName API takes a moniker string and returns the corresponding Package SID [4], which means every Windows 11 machine derives the same S-1-15-2-* for Microsoft.WindowsCalculator_8wekyb3d8bbwe.

Second, a per-package partition of the Object Manager namespace. Every LowBox process's references to global named objects under \BaseNamedObjects are rewritten by the Object Manager to land in \Sessions\<n>\AppContainerNamedObjects\<package-sid>\ and its RPC Control sub-directory. The kernel captures handles to these directories at token-creation time and uses them at name-lookup time; the rewrite is invisible to the application code. We will name the exact field that holds the handles in §5.

Third, an always-Low integrity level. Microsoft Learn states the rule plainly: "if you are in an app container, then the integrity level (IL) is always low" [2]. The AppContainer flag is orthogonal to integrity level, but AppContainer membership forces the integrity level to Low. Two co-tenanted AppContainer processes can therefore both write to \Sessions\<n>\AppContainerNamedObjects\<package-sid>\ (their per-package directory is owned by the package SID) but neither can write to a Medium-IL object outside.

The kernel surface is NtCreateLowBoxToken [3]. Its nine-parameter signature -- the existing token, the desired access, an OBJECT_ATTRIBUTES parameter, the package SID, a capability count and array, a handle count and array -- is the literal data plane for everything we just described. The Win32 surface is CreateAppContainerProfile [27], DeriveAppContainerSidFromAppContainerName [4], the SECURITY_CAPABILITIES struct [28], and the PROC_THREAD_ATTRIBUTE_SECURITY_CAPABILITIES attribute key that UpdateProcThreadAttribute accepts [29]. All five APIs share the same minimum supported client: Windows 8 desktop applications [3] [27] [28].

The corresponding access-check rule is also explicit. Microsoft Learn formalises the dual-principal intersection: "the permitted access is the intersection of that granted by the user/group SIDs and AppContainer SIDs" [30]. We will walk this five-step check field by field in §5.

Ctrl + scroll to zoom
Process creation for a LowBox-token process. The Win32 launcher walks the four-stage process-attribute pipeline; the kernel side dispatches to NtCreateLowBoxToken which stamps the LowBox flag, package SID, and capabilities into the new token before CreateProcess returns.

Three motivations drive the next three generations. The ALL_APP_PACKAGES group SID grants every AppContainer ambient access to a broad default-installed surface; tighter deny-by-default needs the LPAC variant. Win32 applications cannot opt in without source changes; MSIX brings them in via manifest. Kernel exploits bypass the boundary entirely; Windows Sandbox wraps the boundary in Hyper-V.

The implementation correctness motivations are equally specific. James Forshaw's Raising the Dead post on Project Zero in January 2016 walked an issue (P0 Issue 483) in the original NtCreateLowBoxToken plumbing that, in his own words, looked "on the surface" like at best a local denial of service but turned out to be an elevation of privilege [31]. "The root cause of the vulnerability is the NtCreateLowBoxToken system call introduced in Windows 8 to support the creation of locked down tokens for Immersive Applications (formerly known as Metro) as well as IE11's Enhanced Protected Mode" [31]. Microsoft patched the issue in bulletin MS15-111 on October 13, 2015. NVD records the specific CVE within MS15-111 that mapped to Forshaw's writeup as CVE-2015-2554, "Windows Object Reference Elevation of Privilege Vulnerability" [32]. Three years later, Forshaw's Windows Exploitation Tricks: Exploiting Arbitrary Object Directory Creation post (P0 Issue 1550, August 2018) found a related bug in the AppInfo service's helper API: "The AppInfo service, which is responsible for creating the new application, calls the undocumented API CreateAppContainerToken to do some internal housekeeping. Unfortunately this API creates object directories under the user's AppContainerNamedObjects object directory to support redirecting BaseNamedObjects and RPC endpoints by the OS" [33]. The directory was created "with an explicit security descriptor which allows the user full access" [33], and a user-controlled symbolic link in the target could redirect the directory creation almost anywhere in the namespace.

Bridge: ambient access via ALL_APP_PACKAGES motivates the next generation.

4.5 Generation 4: Less Privileged AppContainer (LPAC) (Windows 10 1607, August 2, 2016)

LPAC is one of the most parsimonious changes in the AppContainer chain. Microsoft introduced a synthetic capability with the SID prefix WIN://NOALLAPPPKG; when this capability is present in the new token's Capabilities[] array, the kernel omits the ALL_APP_PACKAGES group SID from the new token. The Windows 10 1607 Anniversary Update was where the mechanism shipped [35]. Microsoft Learn defines LPAC plainly: "Less Privileged AppContainers (LPAC) are even more isolated than regular AppContainers and require further capabilities to gain access to resources that regular AppContainers already have access to such as the registry, files, and others. For example, LPAC cannot open any keys in the registry unless it has the registryRead capability and cannot use COM unless it has the lpacCom capability" [30].

The Chromium repository carries the most explicit user of this surface today. sandbox/policy/win/lpac_capability.h enumerates the LPAC capability constants Chromium passes to its renderer / utility / network-service / GPU process tokens: kLpacChromeInstallFiles, kLpacAppExperience, kLpacCom, kLpacCryptoServices, kLpacEnterprisePolicyChangeNotifications, kLpacIdentityServices, kLpacInstrumentation, kLpacMedia, kLpacPnPNotifications, kLpacPnpNotifications, kLpacServicesManagement, kLpacSessionManagement, kRegistryRead, and several Media Foundation-specific constants [36]. Microsoft Edge, the Chromium-based rebase Microsoft published on January 15, 2020 [37], inherited all of them. The policy RendererAppContainerEnabled documents the Edge consumer specifically: "Launches Renderer processes into an App Container for more security benefits... If you enable this policy, Microsoft Edge launches the renderer process in an app container", available on Windows ≥ 96 [38].

Bridge: LPAC is still a user-mode boundary. A kernel exploit still bypasses it.

4.6 Generation 5: MSIX TrustLevel = appContainer (Windows 10 1809, November 13, 2018)

The Windows 10 October 2018 Update [35] shipped MSIX with an explicit manifest opt-in for AppContainer. The MSIX schema page documents the two values uap10:TrustLevel may take: "mediumIL" and "appContainer" [39]. There are exactly two trust levels, not three. The widely-stated "third trust level" of runFullTrust is in fact a restricted capability that a mediumIL package may declare under its <Capabilities> element to register out-of-process COM and similar legacy-Win32 mechanisms [40]. Microsoft Learn's MSIX container migration page walks the conversion explicitly, showing the manifest going from <rescap:Capability Name="runFullTrust" /> to uap10:TrustLevel="appContainer" [41]. The Wikipedia article on App Installer (which MSIX redirects to) records the App Installer tool's introduction in the Windows 10 1607 Anniversary Update; the MSIX format itself debuted with Windows 10 1809 in 2018 [42].

For developers, the win is that the MSIX deployment stack does all the LowBox plumbing on the application's behalf at install. The application binary itself does not change; the manifest changes, and the App Installer pipeline derives the package SID, creates the profile, and registers the per-package directories.

Bridge: still a user-mode boundary; many packaged apps stay at mediumIL plus runFullTrust.

4.7 Generation 6: Windows Sandbox = AppContainer + Hyper-V (Windows 10 1903, May 21, 2019)

Microsoft announced Windows Sandbox on the Tech Community blog as "a new lightweight desktop environment tailored for safely running applications in isolation" [43]. It shipped in the Windows 10 May 2019 Update [44] [35]. Three architectural primitives carry the design.

The first is the Dynamic Base Image, the pristine read-only file set the sandbox's guest kernel boots from. Microsoft Learn describes its character: "Most OS files are immutable and can be freely shared with Windows Sandbox. A small subset of operating system files are mutable and can't be shared, so the sandbox base image contains pristine copies of them" [45]. Footprint figures from the same page: "Before Windows Sandbox is installed, the dynamic base image package is stored as a compressed 30-MB package. Once installed, the dynamic base image occupies about 500 MB of disk space" [45].

The second is direct-map memory sharing. "when ntdll.dll is loaded into memory in the sandbox, it uses the same physical pages as those pages of the binary when loaded on the host" [45]. Read-only host code does not get re-paged into guest memory; the guest's virtual address space simply maps to the same physical frames.

The third is the host-side AppContainer wrap. The host-side container manager has been reported in security-research write-ups to itself run in a LowBox token, though Microsoft's published Windows Sandbox architecture documentation describes only the Hyper-V partition boundary. The actual containment boundary is the Hyper-V partition: Microsoft Learn's overview is explicit. The sandbox "relies on the Microsoft hypervisor to run a separate kernel that isolates Windows Sandbox from the host" [46]. A kernel exploit inside the sandbox kernel does not reach the host kernel, because the host kernel is on the other side of the Type-1 hypervisor partition.

The 30 MB compressed / 500 MB installed Dynamic Base Image figures come from the Microsoft Learn architecture page [45]; the "few seconds to launch" wall-clock figure and the "data persists through restarts initiated within the sandbox" Windows 11 22H2 persistence behaviour are from the overview page [46]. The persistence behaviour explicitly excludes Windows Home edition.

Bridge: WDAG (the per-tab Edge variant of Hyper-V isolation) was retired in Windows 11 24H2. Per-app Hyper-V isolation is no longer the Microsoft direction. Microsoft Defender Application Guard's overview page documents the retirement: "Microsoft Defender Application Guard, including the Windows Isolated App Launcher APIs, is deprecated for Microsoft Edge for Business and will no longer be updated"; "Starting with Windows 11, version 24H2, Microsoft Defender Application Guard, including the Windows Isolated App Launcher APIs, is no longer available" [47].

GenYearKey ideaWhat it addedFailure that motivated the next
01993Identity equals authorityClassic NT access tokenCannot distinguish two apps as same user
12007Add a mandatory labelIntegrity levels, broker patternNO_READ_UP missing; shared identity
22008Sandbox in user modeBroker / target, restricted tokenNo per-app principal in the kernel
32012Per-app SID alphabetsLowBox flag, package and capability SIDsALL_APP_PACKAGES is broad; Win32 cannot opt in
42016Deny-by-defaultWIN://NOALLAPPPKG strips ALL_APP_PACKAGESStill user-mode; not auto-applied to Win32
52018Manifest opt-in for Win32MSIX TrustLevel="appContainer"Still user-mode; kernel exploit bypasses
62019Hyper-V isolation wrapDynamic Base Image + direct-mapPer-app HV not the direction (WDAG retired)

By 2026 a single Edge browser instance runs the host UI at Medium IL (Gen 0), uses MIC labels (Gen 1), runs a broker / target architecture (Gen 2), launches renderers as LowBox tokens (Gen 3) with WIN://NOALLAPPPKG (Gen 4), is itself an MSIX-packaged app (Gen 5), and can be invoked inside Windows Sandbox (Gen 6). The chain is layered, not successive. The next section opens the LowBox token in WinDbg and walks the five token-level fields that produce these behaviours.

5. The Five Token-Level Fields

If you load WinDbg on a Windows 11 25H2 kernel debugging session and inspect the access token of a UWP calc.exe process with !token, then do the same for a plain notepad.exe, the differences cluster in five fields. Four of them are pointer-valued; one of them is a single bit. Three of them are public in Microsoft's winnt.h-adjacent surface. Two are internal field names that Alex Ionescu reverse-engineered in his Black Hat USA 2015 talk Battle of SKM and IUM: How Windows 10 Rewrites OS Architecture [48], and that James Forshaw walks systematically in his 2024 No Starch Press book Windows Security Internals [1].

5.1 _TOKEN.Flags.LowBoxToken -- the bit

The bit. The kernel's _TOKEN.Flags word carries a LowBoxToken bit that NtCreateLowBoxToken sets and that no later operation modifies [1]. Every kernel access-check path consults this bit when deciding which evaluation rules to apply. If the bit is clear, the token is a classic NT user token and SeAccessCheck proceeds in the 1993 way. If the bit is set, the kernel adds the package-SID claim check, the capability-claim check, and the namespace redirect that we will walk in §5.2 through §5.5.

The bit in _TOKEN.Flags.LowBoxToken is what tells the kernel to evaluate the per-app principal alongside the per-user principal. Everything else in the LowBox token is bookkeeping for that decision.

The other four fields are the bookkeeping.

5.2 _TOKEN.PackageSid -- the package principal

PackageSid is a PSID field in the kernel token structure that carries the S-1-15-2-* SID for the package. The Microsoft surface calls it the AppContainer SID. It is the per-application principal the kernel's access-check path checks DACL entries against. When you mount a per-package ACL like the one in %LOCALAPPDATA%\Packages\Microsoft.WindowsCalculator_8wekyb3d8bbwe\ and find an access control entry naming S-1-15-2-466767348-3739614953-2700836392-..., that ACE is allowing or denying exactly the LowBox process whose PackageSid matches.

Package SID

A PSID value with the prefix S-1-15-2- derived deterministically by SHA-2 hash from the package's family name and used as the per-application principal in DACL evaluations against AppContainer processes [4]. The same package family name produces the same Package SID on every Windows 8 or later machine, which is why per-package directories on disk can be ACL'd to a known SID at install time. The 32-bit sub-authorities are sequential 4-byte slices of the underlying hash.

The signature of DeriveAppContainerSidFromAppContainerName confirms the derivation is intended to be deterministic and reproducible [4]: "Gets the SID of the specified profile", with a Windows 8 minimum supported client. The reverse direction -- start from a Package SID and recover the moniker -- is not feasible without the inverse hash, which is by construction infeasible.

5.3 _TOKEN.Capabilities[] -- the per-capability claim array

Capabilities[] is a kernel array of SID_AND_ATTRIBUTES structures, populated by NtCreateLowBoxToken from the Capabilities parameter the caller passes [3]. Each capability SID lives in the S-1-15-3-* alphabet [5] and represents a specific permission the package declared in its manifest [40]. Each capability is checked by the relevant resource manager: the Windows Filtering Platform checks the internetClient capability SID for outbound network packets, the Object Manager checks namespace capabilities for the per-package directories, the contacts WinRT broker checks the contactsLibrary capability SID against the contacts ACL.

Capability SID

A PSID value with the prefix S-1-15-3- representing a per-package permission [5]. Capability SIDs are stamped into a LowBox token's Capabilities[] array at process creation and consulted by the kernel callout, broker, or kernel access-check path that gates the corresponding resource [30]. The capability vocabulary is open-ended: standard Microsoft-defined capabilities such as internetClient coexist with developer-defined custom capabilities and Chromium's Lpac* synthetic constants.

Microsoft Learn's AppContainer-implementation page formalises the dual-principal access rule for these fields with the same intersection wording quoted in §4.4: the granted access is the intersection of what the user / group SIDs allow and what the AppContainer SIDs allow [30]. The capability-claim check fails closed: a capability the manifest did not declare is not in Capabilities[], the kernel callout does not find a matching claim, and the access fails.

Selected capability SIDs and the resources they gate look like this.

CapabilityWhat it gatesSource
internetClientOutbound TCP/UDP via WFP callout[40]
internetClientServerInbound + outbound network[40]
picturesLibraryRead access to user's Pictures library[40]
documentsLibraryRestricted; access to user Documents[40]
enterpriseAuthenticationRestricted; Kerberos authentication[40]
microphoneAudio input device[40]
webcamVideo input device[40]
locationGeolocation API[40]
runFullTrustRestricted; opt-out of AppContainer for mediumIL packages[40]
WIN://NOALLAPPPKGStrip ALL_APP_PACKAGES from token (LPAC)[30] [36]
lpacComLPAC needs this to use COM[30]
registryReadLPAC needs this to open registry keys[30]

Several rows here have a restricted capability designation in the manifest schema; Microsoft Learn's note on runFullTrust is that "a Medium IL app needs to declare the runFullTrust restricted capability" before it can register out-of-process COM [40]. The same page gives the structural advice every developer should treat as default: "be sure to declare only the capabilities that your app needs" [40].

5.4 _TOKEN.LowboxNumberEntry -- the per-instance number

Two simultaneous Microsoft Calculator processes both carry the same Package SID and the same Capabilities array. What makes them distinct principals to the kernel is the AppContainerNumber -- a per-instance integer assigned by NtCreateLowBoxToken at token-creation time. The kernel maintains a session-scoped AVL tree keyed by this number. Ionescu named the corresponding kernel data structure in his 2015 reverse engineering [48]; the public-facing reference is Forshaw's 2024 book [1].

AppContainerNumber

A per-instance integer assigned by NtCreateLowBoxToken to each LowBox token at creation time and used as the key into the kernel's session-scoped AVL trees that hold the per-instance named-object handles and the per-instance namespace state [1]. Two simultaneously running processes of the same package have the same Package SID but different AppContainerNumber values. This is the field that makes two co-tenanted calculator processes opaque to each other.

The internal field names _TOKEN.Flags.LowBoxToken, the AVL tree at nt!SepLowBoxNumberTable, and the AppContainerNumber are not in any official Microsoft document. The canonical primary sources for them are Ionescu's Black Hat 2015 reverse engineering [48] and Forshaw's 2024 book Windows Security Internals [1]. Microsoft's own NtCreateLowBoxToken page documents the behaviour but does not name the internal fields [3].

5.5 _TOKEN.LowboxHandlesEntry -- the saved namespace handles

LowboxHandlesEntry points into a second AVL tree, keyed by the same AppContainerNumber. The entry carries kernel handles to the per-package directory at \Sessions\<n>\AppContainerNamedObjects\<package-sid>\ and to its RPC Control sub-directory. The handles are captured by NtCreateLowBoxToken (the syscall's last two parameters are HandleCount and Handles[] [3]) and stored in the AVL tree for later lookups.

When a LowBox process calls NtCreateMutant("\\Global\\Foo"), the Object Manager's path-walker (ObpLookupObjectName) consults LowboxHandlesEntry to substitute the rewrite. The lookup proceeds against the per-package directory rather than the global \BaseNamedObjects. The application's request for "Global\Foo" silently resolves to "\Sessions\1\AppContainerNamedObjects\S-1-15-2-...\Foo" -- which is invisible to any other package, because every other package has a different per-instance handle pointing to a different directory.

This is the mechanism Forshaw's Project Zero Issue 1550 attacked in 2018. Forshaw's writeup names the surface: "this API creates object directories under the user's AppContainerNamedObjects object directory to support redirecting BaseNamedObjects and RPC endpoints by the OS" [33]. The implementation bug was in the helper (the AppInfo service's CreateAppContainerToken); the primitive itself is structurally sound.

The five-step LowBox access check

Putting the five fields together, every access decision from a LowBox process runs through this five-step sequence.

Ctrl + scroll to zoom
The five-step LowBox access check. The LowBox flag gates the per-app principal evaluation; the classic DACL walk runs first, MIC labels gate write-up, the package SID claim grants per-package allow ACEs, the capability check gates kernel callouts and broker calls, and the namespace redirect rewrites global named object references.
  1. Classic DACL check. SeAccessCheck walks the object's DACL exactly as if the caller were a normal user. The user SID and group SIDs in the token contribute to the granted-access mask.
  2. MIC label check. The SACL's mandatory-integrity ACE is compared against the token's IntegrityLevel. AppContainer tokens are always Low [2]; if the object's mandatory ACE says NO_WRITE_UP and the request is a write, the access is denied here. The default NO_WRITE_UP-only policy from Vista [9] means a Low-IL LowBox process still cannot write to a default-ACL Medium object.
  3. Package SID claim check. The object's DACL may grant access specifically to the Package SID. If matched, the package SID claim contributes to the granted mask. This is the channel by which per-package data directories are made accessible to the package and only the package.
  4. Capability claim check. A WFP callout, a broker, or a kernel callout checks whether the requested resource maps onto a declared capability. The Windows Filtering Platform compares the outbound socket's destination against the firewall callout's allow list; if the package did not declare internetClient, no S-1-15-3-* capability matches and the connection fails.
  5. Named-object namespace redirect. References to objects under \BaseNamedObjects (mutants, events, sections, RPC endpoints) are rewritten by the Object Manager to \Sessions\<n>\AppContainerNamedObjects\<package-sid>\ before lookup. This is what makes "Global\Foo" mean a per-package object for the LowBox process.

Microsoft Learn's intersection rule is the canonical articulation: "the permitted access is the intersection of that granted by the user/group SIDs and AppContainer SIDs" [30]. A user / group ACE that grants FILE_READ_DATA and a package SID ACE that grants FILE_READ_DATA | FILE_WRITE_DATA together produce FILE_READ_DATA, because the intersection is the smaller set.

Ctrl + scroll to zoom
The kernel _TOKEN data structure with the five LowBox fields highlighted. The LowBoxToken flag gates the rest of the path; PackageSid and Capabilities[] hold the per-app principal and claims; LowboxNumberEntry and LowboxHandlesEntry point into the two session-scoped AVL trees that key per-instance state.

The Win32 launch surface

The minimum production launch sequence has four moving parts. CreateAppContainerProfile derives the Package SID, lays down the per-package profile on disk, and returns the SID and the profile root [27]. InitializeProcThreadAttributeList allocates a process-attribute list. UpdateProcThreadAttribute installs the PROC_THREAD_ATTRIBUTE_SECURITY_CAPABILITIES attribute, whose payload is a SECURITY_CAPABILITIES struct carrying the AppContainer SID, the capability array, and a count [29] [28]. CreateProcess (or CreateProcessAsUser) with STARTUPINFOEX carrying the attribute list launches the new process. Inside the kernel, NtCreateLowBoxToken does the work [3]: it sets _TOKEN.Flags.LowBoxToken, stamps PackageSid, populates Capabilities[], assigns the AppContainerNumber, and saves the directory handles into LowboxHandlesEntry.

TypeScript Conceptual AppContainer launch sequence (TypeScript pseudocode of the four-step Win32 surface)
// This sketches the *shape* of the Win32 launch surface, not real P/Invoke.
// Real callers go through Win32 from C/C++/Rust or via interop.

type PSID = string; // S-1-15-2-... package SIDs
type SECURITY_CAPABILITIES = {
AppContainerSid: PSID;
Capabilities: { Sid: PSID; Attributes: number }[];
};

function createSandboxedProcess(packageName: string, exe: string) {
// Step 1: derive Package SID, create per-package profile on disk.
const packageSid = createAppContainerProfile(packageName, {
  displayName: packageName,
  description: "Sandboxed worker",
  capabilities: ["internetClient"],
});

// Step 2: build the capabilities payload.
const caps: SECURITY_CAPABILITIES = {
  AppContainerSid: packageSid,
  Capabilities: [
    { Sid: "S-1-15-3-1", Attributes: 0 }, // internetClient capability SID
  ],
};

// Step 3: install PROC_THREAD_ATTRIBUTE_SECURITY_CAPABILITIES.
const attrList = initializeProcThreadAttributeList(1);
updateProcThreadAttribute(
  attrList,
  "PROC_THREAD_ATTRIBUTE_SECURITY_CAPABILITIES",
  caps,
);

// Step 4: launch. Kernel calls NtCreateLowBoxToken under the hood.
return createProcess(exe, { startupInfoEx: { attributeList: attrList } });
}

// Demonstration only:
const info = createSandboxedProcess("contoso.WidgetApp_8wekyb3d8bbwe", "widget.exe");
console.log("Launched LowBox PID", info.pid);
console.log("Package SID:", info.packageSid);
console.log("Capabilities granted:", info.caps);

Press Run to execute.

LPAC: one synthetic capability

A LowBox token whose Capabilities[] includes the synthetic WIN://NOALLAPPPKG capability causes the kernel to omit the ALL_APP_PACKAGES group SID from the new token entirely. The token's groups become strictly the package's own derivations, plus the declared capabilities, plus the universal SIDs. Microsoft Learn's wording: "Less Privileged AppContainers (LPAC) are even more isolated than regular AppContainers and require further capabilities to gain access to resources that regular AppContainers already have access to such as the registry, files, and others. For example, LPAC cannot open any keys in the registry unless it has the registryRead capability and cannot use COM unless it has the lpacCom capability" [30]. The Chromium source's lpac_capability.h enumerates the full set Microsoft Edge inherits at renderer launch [36]. Section 6.3 walks the practical consequences.

These five fields and five steps are everything AppContainer is. The next section walks the four places they are exercised at production scale on a 2026 Windows 11 machine: every UWP app, every MSIX-packaged Win32 app, every Edge renderer, and every Windows Sandbox launch.

6. The Four 2026 Production Deployments

AppContainer is not a demonstration primitive. It is the principal mechanism behind every piece of trustworthy code execution on a modern Windows desktop. Four populations exercise it at production scale on a Windows 11 25H2 machine.

6.1 UWP apps

The Microsoft Calculator (Microsoft.WindowsCalculator), the Mail and Calendar apps, Photos, Xbox, Settings, the modern Notepad, and the rest of the Windows-bundled Universal Windows Platform applications are MSIX packages whose manifest declares uap10:TrustLevel="appContainer" [39]. Capabilities are declared explicitly in each manifest's <Capabilities> element [40]. A typical UWP capabilities profile is small: internetClient for a mail client; picturesLibrary for Photos; userAccountInformation for an app that wants the user's display name. The LowBox token is the only principal that ACLs in the per-package data directory at %LOCALAPPDATA%\Packages\<PFN>\ name. The six AppContainer isolation axes -- credential, device, file, network, process, and window isolation -- are listed on Microsoft Learn's AppContainer Isolation page [49], and every UWP app exercises all six. Process isolation is AppContainer-only; UWP apps do not run inside Hyper-V.

6.2 MSIX-packaged desktop apps

The new File Explorer (in 25H2), the new Outlook, Power Automate Desktop, the modernised Snipping Tool, and a growing catalogue of third-party MSIX packages live in a different population. They are packaged using MSIX, and their manifest declares either uap10:TrustLevel="mediumIL" (with <rescap:Capability Name="runFullTrust" />) or uap10:TrustLevel="appContainer" [41] [39]. Many start at mediumIL for legacy interop reasons and gradually migrate as the application drops dependencies on HKLM writes, on absolute file paths, and on registering arbitrary out-of-process COM. Microsoft Learn's MSIX page shows the migration shape: change the manifest from <rescap:Capability Name="runFullTrust" /> to uap10:TrustLevel="appContainer", and the MSIX deployment stack does the LowBox plumbing on the application's behalf at install [41]. The App Installer component is the surface that performs the install [42].

6.3 Microsoft Edge: LPAC renderers

Every Microsoft Edge renderer process on Windows 10 RS5 and later runs as a LowBox token with WIN://NOALLAPPPKG set. The browser is Chromium-based -- "A little over a year ago, we announced our intention to rebuild Microsoft Edge on the Chromium open source project" said the Windows Experience Blog on January 15, 2020 [37] -- and inherits Chromium's broker / target architecture and job-object lockdown [14]. The LPAC layer is the Windows-specific addition. Chromium's lpac_capability.h defines the synthetic capabilities the renderer needs to function with ALL_APP_PACKAGES stripped: kLpacChromeInstallFiles, kLpacCom, kLpacCryptoServices, kLpacIdentityServices, kLpacMedia, kRegistryRead, and the rest [36]. Microsoft's RendererAppContainerEnabled policy documents the customer-facing surface: "Launches Renderer processes into an App Container for more security benefits"; "This policy will only take effect on Windows 10 RS5 and above"; "Windows: ≥ 96"; "If you enable this policy, Microsoft Edge launches the renderer process in an app container" [38]. The policy is rolled out broadly on current Edge channels; the documentation itself notes the unconfigured default will move to in-app-container in a future update [38].

This is the second insight to keep. Modern Microsoft Edge runs all six post-Gen-0 mechanisms simultaneously: Medium IL host UI (Gen 0 baseline), MIC labels on objects (Gen 1), Chromium broker / target architecture (Gen 2), LowBox token on renderers (Gen 3), WIN://NOALLAPPPKG LPAC (Gen 4), MSIX-packaged Edge (Gen 5), and optionally Windows Sandbox (Gen 6). Microsoft and Google reached the same browser-sandbox design from opposite directions, and the production browser uses both. The right question is not "AppContainer or Chromium sandbox?" but "where in the stack does each layer belong?"

6.4 Windows Sandbox

WindowsSandbox.exe -- available on Pro, Enterprise, and Education editions of Windows 10 1903 and later [46] -- launches the most isolated of the four populations. Three layers carry the design. The Hyper-V partition isolates a separate kernel from the host: "It relies on the Microsoft hypervisor to run a separate kernel that isolates Windows Sandbox from the host" [46]. The Dynamic Base Image is the read-only file set the guest kernel boots from, stored as a 30 MB compressed package and unpacked to 500 MB on disk [45]. Direct-map memory sharing means the host's read-only binaries (such as ntdll.dll) "use the same physical pages as those pages of the binary when loaded on the host" [45]. Security-research write-ups report that the host-side container manager that orchestrates this runs in an AppContainer; Microsoft's published architecture page does not document the host-side container-manager token type directly, so the load-bearing isolation property remains the Hyper-V partition itself.

Starting with Windows 11 22H2, in-sandbox restarts persist data: "data persists through restarts initiated within the sandbox" [46]. The persistence is bounded by the sandbox lifecycle; closing the sandbox window discards the guest entirely.

A comparison table for the four populations:

DeploymentYear of shipTrust boundaryCapabilities typicalKernel-exploit defenceHyper-V wrap
UWP apps2012AppContainer1-5, declared in manifestNoNo
MSIX-packaged desktop apps2018AppContainer or mediumILVaries; many declare runFullTrustNoNo
Microsoft Edge LPAC renderers2020 (Edge Chromium GA)LPAC inside Chromium targetSynthetic Lpac* setNoOptional via Windows Sandbox
Windows Sandbox2019Hyper-V partition + AppContainerImplicitYes (separate kernel)Yes
Microsoft Defender Application Guard, the per-tab Hyper-V isolation for Edge that shipped in Windows 10 1709, was retired in Windows 11 24H2 [47]. The replacement is Microsoft Defender SmartScreen plus the Edge Management Service; the per-tab Hyper-V boundary is gone. Per-application hypervisor isolation is no longer the Microsoft direction; Windows Sandbox is the surviving Hyper-V-wrapped variant.

On the same machine, the same kernel, the same SeAccessCheck runs the same five-step LowBox path millions of times a second across these four populations. Yet the LowBox token is not what every OS does. The next section asks: how do macOS, iOS, Android, and Linux solve the same problem -- and what do the differences teach us about kernel-token-side enforcement versus user-mode-policy-side enforcement?

7. Competing Approaches Across Operating Systems

Apple, Google, and the Linux distributions solved the same problem -- how does the kernel give two co-tenanted applications different verdicts? -- with four structurally different answers. Each trade-off is a different bet on where in the system the per-app principal should live.

iOS and iPadOS application sandbox. Apple ships a mandatory per-app sandbox on every device since iPhone OS 1 in 2007 [17]. From iPhone OS 2.0 / the 2008 App Store launch onward, the developer-facing principal is two-valued: a Bundle ID (developer-chosen string) and a Team ID (signer identity). Per-app entitlements declared in the signed bundle are the capability vocabulary. Enforcement is mandatory -- there is no opt-out. The per-app filesystem container at Containers/Data/Application/<bundle-uuid>/ is the iOS analogue of %LOCALAPPDATA%\Packages\<PFN>\. Where Windows extends the kernel token, iOS keeps the per-app profile in a TrustedBSD-derived MAC framework and consults it from kernel mode at every relevant resource manager.

macOS App Sandbox. macOS uses the same entitlement primitive Apple developed for iOS, plus a user-mode policy daemon (sandboxd) that holds the per-app profile [51]. The trade-off is that more decisions are made in user mode than on iOS, with corresponding flexibility costs. App Sandbox is optional on macOS for non-App-Store distribution, in contrast to iOS, where it is mandatory.

Android per-app UID plus SELinux plus seccomp-bpf. Android's Application Sandbox page on the AOSP documents the layered model: every app receives a distinct UNIX UID; classical UNIX discretionary access control enforces per-app isolation; SELinux mandatory access control is layered on top from Android 5.0 onward; per-physical-user partitions arrived in Android 6.0; the seccomp-bpf system-call filter is required from Android 8.0; per-app SELinux sandboxes apply for targetSdkVersion >= 28 (Android 9); and path-based file restrictions tightened in Android 10 [19]. The kernel-side per-app principal is the UNIX UID. The MAC layers above add additional confinement.

Linux unprivileged namespaces plus seccomp plus AppArmor / SELinux plus Flatpak / Snap. Linux's per-application sandbox is composable. No first-class per-app principal lives in the kernel. The application sandboxes are layered above the user-keyed DAC: Flatpak and Snap build on unprivileged user namespaces and seccomp filters; Chromium on Linux uses the same kit. The Chromium FAQ's kernel-bugs caveat from §3 applies in every cross-OS configuration: a user-mode sandbox cannot defend against bugs in the kernel it runs on [12].

The structural axis falls out cleanly. macOS keeps the per-app profile in user-mode outside the kernel token; iOS keeps it in user-mode but enforces mandatorily; Android allocates a real UNIX UID; Windows extends the kernel-token SID alphabet. Windows is the only one of the four that partitions the kernel data structure.

Operating systemPrimitiveYearWhere the principal livesPer-call cost modelKernel-exploit containmentMandatory?
Windows 8+LowBox token (AppContainer)2012Inside the access token (kernel)Inline in SeAccessCheckNoOpt-in via manifest / SDK
macOSApp Sandbox + entitlements2011 (Mac App Store)User-mode sandboxd profileIPC for some decisionsNoOpt-in (Mac App Store: yes)
iOS / iPadOSApp Sandbox + entitlements2007TrustedBSD MAC frameworkInline kernel checkNo (Pegasus class proves)Yes, mandatory
AndroidUID + SELinux + seccomp2008UID space (kernel) + MACFour checks per syscallNoYes, mandatory
LinuxNamespaces + seccomp + Flatpak / Snap2014 (Flatpak)Composable user-mode + kernelVariable per layerNoOpt-in per app

"The sandbox is not a security silver bullet, but it is a strong last defense against nasty exploits." -- Chromium sandbox FAQ [12]

The Chromium project itself ports its broker / target sandbox across all four families. On Windows it sits on top of AppContainer and LPAC. On macOS it uses seatbelt. On Linux it uses seccomp filters plus unprivileged user namespaces. On ChromeOS the same code talks to ChromeOS's own kernel-side enforcement. The broker / target pattern is operating-system-independent; what differs is the per-OS capability vocabulary the broker negotiates with [14].

Putting the principal in the kernel access token is fast and elegant. The amortised cost of the LowBox path is one extra DACL pass plus the capability-claim check, all running inline in SeAccessCheck with no IPC round-trip. But the kernel-side bet has a brittle edge: it is brittle exactly where putting it in the kernel is not enough. The next section asks what the LowBox token cannot prove.

8. Theoretical Limits: What the LowBox Token Cannot Prove

Every security primitive has a perimeter beyond which it can no longer reason. The LowBox token has five.

Limit 1: Kernel exploits. Once the attacker is in kernel mode, they rewrite their own token. The LowBox bit becomes irrelevant. The Chromium sandbox FAQ states the principle plainly: "the sandbox cannot provide any protection against bugs in system components such as the kernel it is running on" [12]. This is the load-bearing argument for Windows Sandbox's Hyper-V wrap (§4.7, §6.4). It is the third insight to keep.

Limit 2: Confused-deputy brokers. A broker process outside the AppContainer is, by design, the bridge back to user-scoped resources. If the broker honours requests it should not have honoured, the AppContainer's caller succeeds in doing something it could not have done directly. The canonical class on Windows is RuntimeBroker, AppInfo (the UAC consent broker), Print, WebAuthn, voice activation, and the Microsoft (R) Diagnostics Hub Standard Collector Service that Forshaw called "DiagHub for short" in his 2018 arbitrary-file-write writeup [34]. The 1988 Confused Deputy paper from the capability-systems literature [52] is the literature anchor for this whole class.

Limit 3: Token-stealing. An attacker who can duplicate a higher-privilege token via NtDuplicateToken, NtOpenProcessTokenEx, or any of the SeImpersonatePrivilege-stealing Potato-family attacks steps out of the AppContainer by impersonating a non-LowBox user. Siloscape is the most-publicised Windows container escape: Daniel Prizmant's Unit 42 writeup characterises it as "the first known malware targeting Windows containers", and records Microsoft's initial position that "Windows Server containers are not a security boundary" before later reclassifying that "an escape from a Windows container to the host, when executed without administrator permissions inside the container, will in fact be considered a vulnerability" [53]. Token-stealing is the same class one rung down: an AppContainer escape via impersonation.

Limit 4: Capability granularity. internetClient is "the application can speak to the public internet" with no per-host granularity. Each Windows capability is approximately as fine-grained as a Linux CAP_*, not as fine-grained as an iOS entitlement key. There is no AppContainer-native equivalent of "this app can connect to api.example.com:443 but nowhere else." The Microsoft Learn capabilities page enumerates the capability vocabulary [40]; the cardinality is in the dozens of standard capabilities plus custom ones, not in the millions.

Limit 5: In-process side channels. Once data is in the AppContainer process's address space, the AppContainer model has nothing to say about it. Hardware side channels (Spectre, MDS, Downfall), explicit channels (clipboard, WebRTC, browser-tab side channels in Edge), and out-of-band exfiltration via broker calls are all out of model. AppContainer is a boundary primitive; once you are inside the boundary, the primitive does not constrain in-process behaviour.

These five limits define the research surface post-2024. The next section catalogues what is still open.

9. Open Problems

Six open problem classes are actively investigated in 2024-2026 research.

  1. The ALL_APP_PACKAGES ambient-access surface. Even with LPAC, many default-installed resources are ACL'd to the ALL_APP_PACKAGES group; non-LPAC AppContainers inherit access to all of them. The research class is to enumerate the union of all ALL_APP_PACKAGES-readable surfaces on a default Windows install and classify which leak cross-package data.

  2. Capability-SID collisions and over-grant. Third-party custom capability SIDs are derived from a string in the manifest; the collision resistance of the hash construction under adversarial choice of input string is an open question. A malicious manifest that produces a capability SID colliding with a privileged Microsoft-defined capability would be a structural break.

  3. LPAC capability-injection at process creation. The capability list is supplied by the creator of the AppContainer process; tightening which caller can ask for which capability has been a recurring servicing-bulletin theme. Forshaw's Raising the Dead writeup (P0 Issue 483, fixed in MS15-111 as CVE-2015-2554 [31] [32]) and the 2018 Arbitrary Object Directory Creation writeup (P0 Issue 1550 [33]) are the canonical examples of bugs in this class.

  4. Hyper-V-per-AppContainer ("HVCI for AppContainers"). WDAG's 2024 retirement [47] leaves a gap: there is no production direction for per-application hypervisor isolation. Windows Sandbox is the surviving Hyper-V-wrapped sandbox; per-tab or per-app HV isolation in Edge is not coming back. The research question is whether per-app Hyper-V can be reintroduced in a form that does not have WDAG's adoption problems.

  5. Cross-package AppContainer-to-AppContainer attacks. As third-party MSIX adoption grows, the cross-package attack surface (one third-party package abusing another's \AppContainerNamedObjects\<other-package-sid>\ ACL) grows. The 2018 P0 1550 writeup [33] is the canonical example of a kernel-side variant; user-mode variants in third-party MSIX brokers are the next class.

  6. Post-CrowdStrike user-mode EDR runtime. After the July 2024 incident, Microsoft convened a multi-vendor endpoint-security summit and committed to a more isolated EDR / AV runtime in user mode. AppContainer or LPAC is one of the candidate runtimes for the new platform; architectural details are still being published.

For Problem 1 specifically, the standard tool for enumerating the ALL_APP_PACKAGES-readable surface is Forshaw's NtObjectManager PowerShell module's Get-AccessibleObject -ProcessId <pid> cmdlet -- it enumerates every kernel object a given process can reach, which is the right primitive for asking "what does an ALL_APP_PACKAGES member actually see?" The companion Microsoft tool is LaunchAppContainer from the official SandboxSecurityTools repository on GitHub [50].

The unresolved problems share a structural property: they sit between the token-level guarantee AppContainer makes and the resource managers that implement the consequences. The next section gives practical guidance for developers and practitioners working within these limits today.

10. Practical Guide

Two audiences need different answers. Developers need to know how to opt their code in. Practitioners need to know how to audit the deployment.

For developers

Package your Win32 app with MSIX and set uap10:TrustLevel="appContainer" in the manifest's <Application> element [39]. Stop adding runFullTrust as a restricted capability by default; the manifest is a budget, and every restricted capability is a lifetime ACL on your package SID [40] [41].

Declare only the capabilities your app needs in <Capabilities>. Microsoft Learn's wording is exactly this: "be sure to declare only the capabilities that your app needs" [40]. Each extra internetClient or picturesLibrary is a lifetime allow ACE on the corresponding Capability SID.

Use LPAC for any process that does not need cross-package or cross-user resource access. The mechanism is the synthetic WIN://NOALLAPPPKG capability in SECURITY_CAPABILITIES.Capabilities[] at process creation [30] [36]. The Chromium tree's lpac_capability.h is the canonical reference for which LPAC capabilities each kind of worker process needs [36].

Test your sandbox with Forshaw's NtObjectManager PowerShell module's Get-AccessibleObject -ProcessId <pid> cmdlet, which enumerates every kernel object your process can actually reach [50]. Tighten capabilities until the enumerated list matches your expectations. Microsoft's own SandboxSecurityTools repository ships LaunchAppContainer for the same kind of testing in the Insider bounty programme [50].

For practitioners

Identify which high-risk applications on your managed fleet can be MSIX-packaged and migrated to uap10:TrustLevel="appContainer". Browsers, PDF viewers, and email clients are highest payoff because hostile content reaches them most often.

Audit the per-package directory permissions in %LOCALAPPDATA%\Packages\<PFN>\. The LocalState, RoamingState, and AC subdirectories are the load-bearing entries; each should grant access to the package SID, not to broad groups.

Use Windows Sandbox (WindowsSandbox.exe) for Hyper-V-isolated execution of untrusted programs on Pro, Enterprise, or Education editions [46]. Configurations are described in a .wsb file: a 30 MB Dynamic Base Image launches in a few seconds, and Windows 11 22H2 onward preserves data through in-sandbox restarts.

Monitor the Microsoft-Windows-AppxPackaging/Operational and Microsoft-Windows-AppXDeploymentServer/Operational event logs for unexpected CreateAppContainerToken failures and capability mismatches. Microsoft Learn's AppX troubleshooting page names these two channels verbatim and walks the diagnostic surface they expose [54].

Enumerate the full surface a given AppContainer process can reach

Once NtObjectManager is installed (from PowerShell Gallery), a defender can dump the complete reachable kernel-object set for a running LowBox process:

Install-Module NtObjectManager -Scope CurrentUser
$pid = (Get-Process -Name calc).Id
Get-AccessibleObject -ProcessId $pid -TypeFilter Mutant,Section,Event,Directory |
  Sort-Object Path | Format-Table -Property TypeName, Path, GrantedAccess

The output enumerates every named kernel object the LowBox token can open, with the access mask the kernel would grant on each request. Any path that resolves outside \Sessions\<n>\AppContainerNamedObjects\<package-sid>\ is a candidate for cross-package leakage or an over-permissive capability. This is the same surface §9 problem 1 catalogues [50].

The practical guidance only matters if the deployment is correctly understood. The next section addresses the most common misconceptions.

11. Frequently Asked Questions

Common questions about AppContainer and LowBox tokens

Is AppContainer the same as Low Integrity Level?

No. AppContainer and integrity level are orthogonal axes. AppContainer is a per-application principal in the access token; integrity level is a mandatory label. Microsoft Learn states the relationship plainly: "if you are in an app container, then the integrity level (IL) is always low" -- but the converse is not true. Plenty of Low-IL tokens are not AppContainer tokens (the IE 7 Protected Mode renderer was the historical example; the LocalLow workspace and the Low-IL Chromium target are modern examples) [2].

Why does my UWP app see a different C:\Windows\Temp than my Win32 app?

Because the LowBox process's Object Manager namespace is partitioned at \Sessions\<n>\AppContainerNamedObjects\<package-sid>\, and the WinRT API the UWP app uses for Windows.Storage.TempFolder resolves a per-package temporary directory under %LOCALAPPDATA%\Packages\<PFN>\AC\Temp\ instead of the global \BaseNamedObjects-anchored C:\Windows\Temp. The kernel handles for the rewrite live in the LowboxHandlesEntry AVL-tree slot keyed by your process's AppContainerNumber.

What's the difference between AppContainer, LowBox, and LPAC?

LowBox is the kernel-internal name preserved in NtCreateLowBoxToken and the _TOKEN.Flags.LowBoxToken bit [2] [3]. AppContainer is the public Win32 / WinRT API name for the same kernel object. LPAC (Less Privileged AppContainer) is the variant where the synthetic WIN://NOALLAPPPKG capability strips the implicit ALL_APP_PACKAGES group SID from the new token, requiring the package to declare each access (registryRead, lpacCom, and others) explicitly [30].

Why is the Package SID so long? What do the sub-authorities mean?

Because the Package SID is a deterministic hash of the Package Family Name (which is itself a hash of the publisher distinguished name plus the package moniker). Each of the eight 32-bit sub-authorities is a 4-byte slice of the underlying SHA-256 hash (8 × 4 bytes = 32 bytes = 256 bits). The point of the construction is that every Windows 8 or later machine derives the same Package SID for the same Package Family Name, so per-package directory DACLs can be ACL'd at install time to a known SID [4] [1].

Can two instances of the same package see each other's named objects?

No. The kernel's AppContainerNumber per-instance counter keys each instance into its own slot in nt!SepLowBoxHandlesTable, and the Object Manager rewrites \BaseNamedObjects references against the per-instance saved-handle directory before name lookup [1]. Two Calculator processes share a Package SID and a Capabilities array but have different AppContainerNumbers; the named objects each one creates land in different directories.

Does ALL_APP_PACKAGES mean every AppContainer can read it?

Yes -- unless the AppContainer has WIN://NOALLAPPPKG, in which case it is LPAC and ALL_APP_PACKAGES is omitted from its token [30] [36]. The ALL_APP_PACKAGES ambient-access surface is the §9 problem-1 research class. The standard tool for enumerating what an ALL_APP_PACKAGES member can reach on a given system is the Get-AccessibleObject cmdlet in Forshaw's NtObjectManager PowerShell module, and Microsoft publishes its own LaunchAppContainer testing tool in SandboxSecurityTools [50].

Is Windows Sandbox just a fancy AppContainer?

No. Windows Sandbox combines a separate Hyper-V partition running a pristine Windows kernel from the Dynamic Base Image [45] with -- according to security-research reverse-engineering write-ups -- an AppContainer wrap on the host-side container manager. The Hyper-V layer is the only documented structural defence against kernel exploits inside the sandbox; pure AppContainer cannot defend against a kernel exploit. Inside the sandbox you still see the LowBox plumbing (it is a Windows guest, after all), but the meaningful trust boundary is the hypervisor partition.

12. Where This Plane Connects to the Others

AppContainer is the principal layer of the modern Windows sandbox stack. It is not the whole stack. A correct modern Windows app launch crosses four single-purpose layers in the kernel and in the deployment pipeline, and each layer carries a separate guarantee.

  1. Code identity. Who is this code? Authenticode signatures, kernel-mode code signing, the MSIX signing pipeline, and the Package Family Name derivation answer that question [4].
  2. AppContainer / LowBox token. What principal is the running instance? NtCreateLowBoxToken sets the LowBox flag, stamps the Package SID, and populates Capabilities[] [3].
  3. Object Manager namespace partition. What names can the principal resolve? LowboxHandlesEntry directs the path-walker to the per-package \AppContainerNamedObjects\<package-sid>\ directory [1].
  4. Process mitigation policies. What is the principal allowed to do inside its own address space? Arbitrary Code Guard, Code Integrity Guard, Control Flow Guard, Extended Flow Guard, Hardware-enforced Stack Protection (CET), and ImageLoadPolicy are the in-process mitigations Windows applies on top of the per-app principal, exposed via the PROCESS_MITIGATION_POLICY enumeration that SetProcessMitigationPolicy accepts [55].

Walk a modern Windows app boot. Authenticode and the MSIX signing pipeline verify the binaries. The MSIX deployment stack derives the Package SID from the Package Family Name and writes the per-package profile under %LOCALAPPDATA%\Packages\<PFN>\. The launcher calls CreateProcess with a SECURITY_CAPABILITIES payload, which calls NtCreateLowBoxToken in the kernel. NtCreateLowBoxToken sets the LowBox flag and the per-instance fields. From that point every later SeAccessCheck against any object the process opens consults the new token's per-app fields alongside the classic user / groups walk. The Object Manager namespace gets partitioned in the kernel's hash table by the AppContainerNumber. The in-process mitigation policies decide what code may execute and which DLLs may load.

Ctrl + scroll to zoom
The four-layer architecture of a modern Windows app launch. Each layer is single-purpose and answers one of the four-axis questions the classic NT token model could not. Together they cover what code identity, runtime principal, namespace resolution, and in-process behaviour mean in 2026 Windows.

Each layer is single-purpose. Together they cover the four-axis system the classic NT token model could not.

"The LowBox bit is the answer to the question Windows NT 3.1 couldn't ask. Everything else is bookkeeping."

Two calculators on the same Windows 11 machine give the kernel a single question with two verdicts. The bit in _TOKEN.Flags.LowBoxToken is the one-line answer Windows took fourteen years to ship -- and the work Microsoft did in the years between January 30, 2007 and October 26, 2012 is what made it possible to ask the question at all.

Study guide

Key terms

LowBox token
An access token whose _TOKEN.Flags.LowBoxToken bit is set, marking the process as an AppContainer process whose access checks consult the package SID, capability SIDs, and per-instance namespace fields.
Package SID
A deterministic SHA-2-derived SID with prefix S-1-15-2-* that names a specific MSIX/UWP package.
Capability SID
A SID with prefix S-1-15-3-* representing a per-package permission declared in the application manifest.
AppContainerNumber
A per-instance integer assigned by NtCreateLowBoxToken that keys per-instance state in the kernel's session-scoped AVL trees.
LPAC
Less Privileged AppContainer -- a LowBox token whose WIN://NOALLAPPPKG capability strips the ALL_APP_PACKAGES group SID for stricter deny-by-default.
Mandatory Integrity Control
Vista-era mechanism adding an integrity level (Low/Medium/High/System) to every process and securable object; AppContainer tokens are always Low IL.
Dynamic Base Image
Windows Sandbox's read-only file set, stored as a 30 MB compressed package and unpacked to 500 MB, that a fresh Hyper-V partition boots from.

Comprehension questions

  1. Which kernel data-structure field distinguishes a UWP calc.exe from a legacy win32calc.exe even when every classic NT token field is identical?

    _TOKEN.Flags.LowBoxToken, the bit set by NtCreateLowBoxToken and consulted by every AppContainer-aware access-check path.

  2. Why are two co-tenanted instances of the same package different principals to the kernel?

    Because NtCreateLowBoxToken assigns a fresh AppContainerNumber per instance and the Object Manager keys the per-instance namespace handles on that number.

  3. Name the synthetic capability that turns an AppContainer into an LPAC.

    WIN://NOALLAPPPKG -- its presence in Capabilities[] causes NtCreateLowBoxToken to omit the ALL_APP_PACKAGES group SID from the new token.

  4. What is the only structural defence against kernel exploits inside an AppContainer?

    Hypervisor isolation. Windows Sandbox wraps an AppContainer-managed guest in a separate Hyper-V partition with its own kernel.

  5. Cite the Microsoft Learn intersection rule for AppContainer access checks.

    'the permitted access is the intersection of that granted by the user/group SIDs and AppContainer SIDs' -- the dual-principal rule that runs on every LowBox access decision.

References

  1. James Forshaw (2024). Windows Security Internals. No Starch Press. https://nostarch.com/windows-security-internals ISBN 978-1-7185-0198-0.
  2. AppContainer for legacy applications. Microsoft Learn. https://learn.microsoft.com/en-us/windows/win32/secauthz/appcontainer-for-legacy-applications- - Canonical source for the LowBox -> AppContainer rename and the always-Low-IL rule.
  3. NtCreateLowBoxToken function. Microsoft Learn. https://learn.microsoft.com/en-us/windows/win32/secauthz/ntcreatelowboxtoken - Nine-parameter prototype, Windows 8 minimum, medium-or-higher IL caller required.
  4. DeriveAppContainerSidFromAppContainerName function (userenv.h). Microsoft Learn. https://learn.microsoft.com/en-us/windows/win32/api/userenv/nf-userenv-deriveappcontainersidfromappcontainername
  5. Well-known SIDs. Microsoft Learn. https://learn.microsoft.com/en-us/windows/win32/secauthz/well-known-sids
  6. Windows Vista. Wikipedia. https://en.wikipedia.org/wiki/Windows_Vista
  7. User Account Control. Wikipedia. https://en.wikipedia.org/wiki/User_Account_Control
  8. Mandatory Integrity Control. Wikipedia. https://en.wikipedia.org/wiki/Mandatory_Integrity_Control
  9. Mandatory Integrity Control. Microsoft Learn. https://learn.microsoft.com/en-us/windows/win32/secauthz/mandatory-integrity-control
  10. Internet Explorer 7. Wikipedia. https://en.wikipedia.org/wiki/Internet_Explorer_7
  11. Marc Silbey & Peter Brundrett (2006). Understanding and Working in Protected Mode Internet Explorer (mirror). Digital Detective (mirror of retired MSDN article). https://kb.digital-detective.net/display/BF/Understanding+and+Working+in+Protected+Mode+Internet+Explorer
  12. Chromium Sandbox FAQ. Chromium. https://chromium.googlesource.com/chromium/src/+/HEAD/docs/design/sandbox_faq.md
  13. James Forshaw (2021). Understanding Network Access in Windows AppContainers. Project Zero. https://googleprojectzero.blogspot.com/2021/08/understanding-network-access-windows-app.html
  14. Chromium Sandbox design. Chromium. https://chromium.googlesource.com/chromium/src/+/HEAD/docs/design/sandbox.md
  15. Bennet Yee, David Sehr, Gregory Dardyk, J. Bradley Chen, Robert Muth, Tavis Ormandy, Shiki Okasaka, Neha Narula, & Nicholas Fullagar (2009). Native Client: A Sandbox for Portable, Untrusted x86 Native Code. IEEE Symposium on Security and Privacy. https://doi.org/10.1109/SP.2009.25
  16. Google Native Client. Wikipedia. https://en.wikipedia.org/wiki/Google_Native_Client
  17. App security overview (Apple Platform Security). Apple Support. https://support.apple.com/guide/security/app-security-overview-sec35dd877d0/web - iOS / iPadOS-side primary for the strict-sandboxing-plus-code-signing app security model; the cross-platform analogue is also documented.
  18. Android version history. Wikipedia. https://en.wikipedia.org/wiki/Android_version_history
  19. Application Sandbox. Android Open Source Project. https://source.android.com/docs/security/app-sandbox
  20. Crispin Cowan, Calton Pu, Dave Maier, Jonathan Walpole, Peat Bakke, Steve Beattie, Aaron Grier, Perry Wagle, Qian Zhang, & Heather Hinton (1998). StackGuard: Automatic Adaptive Detection and Prevention of Buffer-Overflow Attacks. 7th USENIX Security Symposium. https://www.usenix.org/conference/7th-usenix-security-symposium/stackguard-automatic-adaptive-detection-and-prevention
  21. (2008). Linux security guru joins Microsoft. ZDNet. https://www.zdnet.com/article/linux-security-guru-joins-microsoft/
  22. Crispin Cowan (2013). Windows 8 Security: Supporting User Confidence. USENIX Security 22. https://www.usenix.org/conference/usenixsecurity13/windows-8-security-supporting-user-confidence
  23. (2019). Crispin Cowan -- CrySP Speaker Series. University of Waterloo. https://crysp.uwaterloo.ca/speakers/20191101-Cowan
  24. Windows 8. Wikipedia. https://en.wikipedia.org/wiki/Windows_8
  25. (2012). Windows 8 has reached the RTM milestone!. Windows Experience Blog. https://blogs.windows.com/windowsexperience/2012/08/01/windows-8-has-reached-the-rtm-milestone/
  26. Pavel Yosifovich, Alex Ionescu, Mark E. Russinovich, & David A. Solomon (2017). Windows Internals, Part 1, 7th Edition. Microsoft Press. https://www.microsoftpressstore.com/store/windows-internals-part-1-system-architecture-processes-9780735684188 ISBN 978-0-7356-8418-8.
  27. CreateAppContainerProfile function (userenv.h). Microsoft Learn. https://learn.microsoft.com/en-us/windows/win32/api/userenv/nf-userenv-createappcontainerprofile
  28. SECURITY_CAPABILITIES structure (winnt.h). Microsoft Learn. https://learn.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-security_capabilities
  29. UpdateProcThreadAttribute function (processthreadsapi.h). Microsoft Learn. https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-updateprocthreadattribute
  30. Implementing an AppContainer. Microsoft Learn. https://learn.microsoft.com/en-us/windows/win32/secauthz/implementing-an-appcontainer
  31. James Forshaw (2016). Raising the Dead. Project Zero. https://projectzero.google/2016/01/raising-dead.html
  32. (2015). CVE-2015-2554: Windows Object Reference Elevation of Privilege Vulnerability. NIST National Vulnerability Database. https://nvd.nist.gov/vuln/detail/CVE-2015-2554
  33. James Forshaw (2018). Windows Exploitation Tricks: Exploiting Arbitrary Object Directory Creation for Local Elevation of Privilege. Project Zero. https://googleprojectzero.blogspot.com/2018/08/windows-exploitation-tricks-exploiting.html
  34. James Forshaw (2018). Windows Exploitation Tricks: Exploiting Arbitrary File Writes for Local Elevation of Privilege. Project Zero. https://googleprojectzero.blogspot.com/2018/04/windows-exploitation-tricks-exploiting.html
  35. Windows 10 version history. Wikipedia. https://en.wikipedia.org/wiki/Windows_10_version_history
  36. sandbox/policy/win/lpac_capability.h. Chromium source. https://chromium.googlesource.com/chromium/src/+/main/sandbox/policy/win/lpac_capability.h?format=TEXT
  37. (2020). New year, new browser: the new Microsoft Edge is out of preview. Windows Experience Blog. https://blogs.windows.com/windowsexperience/2020/01/15/new-year-new-browser-the-new-microsoft-edge-is-out-of-preview-and-now-available-for-download/
  38. RendererAppContainerEnabled (Microsoft Edge policy). Microsoft Learn. https://learn.microsoft.com/en-us/deployedge/microsoft-edge-browser-policies/rendererappcontainerenabled
  39. Application (in uap10 manifest schema). Microsoft Learn. https://learn.microsoft.com/en-us/uwp/schemas/appxpackage/uapmanifestschema/element-application
  40. App capability declarations. Microsoft Learn. https://learn.microsoft.com/en-us/windows/uwp/packaging/app-capability-declarations
  41. Run an MSIX app in the AppContainer environment. Microsoft Learn. https://learn.microsoft.com/en-us/windows/msix/msix-container
  42. MSIX. Wikipedia. https://en.wikipedia.org/wiki/MSIX
  43. Hari Pulapaka (2018). Windows Sandbox (announcement). Microsoft Tech Community. https://techcommunity.microsoft.com/blog/windowsosplatform/windows-sandbox/301849
  44. (2019). How to get the Windows 10 May 2019 Update. Windows Experience Blog. https://blogs.windows.com/windowsexperience/2019/05/21/how-to-get-the-windows-10-may-2019-update/
  45. Windows Sandbox architecture. Microsoft Learn. https://learn.microsoft.com/en-us/windows/security/application-security/application-isolation/windows-sandbox/windows-sandbox-architecture
  46. Windows Sandbox overview. Microsoft Learn. https://learn.microsoft.com/en-us/windows/security/application-security/application-isolation/windows-sandbox/windows-sandbox-overview
  47. Microsoft Defender Application Guard overview. Microsoft Learn. https://learn.microsoft.com/en-us/windows/security/application-security/application-isolation/microsoft-defender-application-guard/md-app-guard-overview
  48. Alex Ionescu (2015). Battle of SKM and IUM: How Windows 10 Rewrites OS Architecture. Black Hat USA 2015. https://github.com/tpn/pdfs/blob/master/Battle%20of%20SKM%20and%20IUM%20-%20How%20Windows%2010%20Rewrites%20OS%20Architecture%20-%20Alex%20Ionescu%20-%202015%20(blackhat2015).pdf
  49. AppContainer Isolation. Microsoft Learn. https://learn.microsoft.com/en-us/windows/win32/secauthz/appcontainer-isolation - The six isolation axes: credential, device, file, network, process, window.
  50. microsoft/SandboxSecurityTools. GitHub. https://github.com/microsoft/SandboxSecurityTools
  51. About App Sandbox. Apple Developer. https://developer.apple.com/documentation/security/app-sandbox - macOS App Sandbox developer documentation. Restricted to macOS-specific claims after Stage 10.
  52. Norm Hardy (1988). The Confused Deputy (or why capabilities might have been invented). ACM Operating Systems Review 22(4). https://doi.org/10.1145/54289.871709 - The 1988 capability-systems-literature anchor for the confused-deputy class of brokered-access bugs. Hardy was Senior Architect at Key Logic, Inc.; the cap-lore.com mirror preserves the full original Operating Systems Review text.
  53. Daniel Prizmant (2021). Siloscape: First Known Malware Targeting Windows Containers. Palo Alto Networks Unit 42. https://unit42.paloaltonetworks.com/siloscape/
  54. Troubleshooting packaging, deployment, and query of Windows apps. Microsoft Learn. https://learn.microsoft.com/en-us/windows/win32/appxpkg/troubleshooting - Names the two Microsoft-Windows-AppxPackaging/Operational and Microsoft-Windows-AppXDeploymentServer/Operational event-log channels under Applications and Services Logs > Microsoft > Windows.
  55. PROCESS_MITIGATION_POLICY enumeration (winnt.h). Microsoft Learn. https://learn.microsoft.com/en-us/windows/win32/api/winnt/ne-winnt-process_mitigation_policy - Canonical enumeration of the per-process mitigation policies (DEP, ASLR, DynamicCode, ControlFlowGuard, ImageLoad, UserShadowStack, RedirectionTrust, and others) that SetProcessMitigationPolicy accepts. The primary source for the §12 layer-4 enumeration of in-process mitigations.