A deep dive into how Sandy manipulates DACLs, SIDs, and ACL Pipelines to achieve perfect, leak-free isolation in both AppContainer and Restricted Token modes.
The fundamentals of the Windows Security Model and Sandy's per-instance isolation architecture.
A SID is a unique text or binary string representing a user or group. Both Sandbox modes rely on unique, per-instance SIDs, not a shared identity. This guarantees zero crossover between concurrent sandboxes.
S-1-15-2-<uuid>)SECURITY_RESOURCE_MANAGER_AUTHORITY (e.g., S-1-9-<uuid>)Every file and folder on Windows has a Security Descriptor containing a DACL (Discretionary Access Control List). A DACL is a list of Access Control Entries (ACEs). An ACE binds a SID to a Permission Mask (e.g., "Allow S-1-9-123 to Read").
Sandy translates your [allow.*] rules into ACEs. [deny.*] is only supported in Restricted Token mode — AppContainer mode rejects deny rules at config validation time.
The Windows Kernel silently ignores standard DENY_ACCESS ACEs when evaluating access for an AppContainer SID. Sandy therefore rejects [deny.*] for AppContainer mode at config validation time (exit 128). Use Restricted Token mode for deny rules.—Mask Reduction—for AC.
[allow.deep]
read = ['C:\Data']
| Pipeline | Action |
|---|---|
| Restricted Token | Injects an ACCESS_ALLOWED_ACE for S-1-9-... with the Read mask. Done. |
| AppContainer | Injects an ACCESS_ALLOWED_ACE for S-1-15-2-... with the Read mask. Done. |
[allow.deep]
all = ['C:\Data']
[deny.deep]
write = ['C:\Data']
| Pipeline | Action |
|---|---|
| Restricted Token | Injects a DENY_ACCESS_ACE (Write) before the ACCESS_ALLOWED_ACE (All). Windows evaluates Deny first. |
| AppContainer | Since DENY_ACCESS is ignored, Sandy performs Mask Reduction. It subtracts Write bits from the All mask (preserving shared Read bits like SYNCHRONIZE), and injects a single ACCESS_ALLOWED_ACE with the resulting (All - Write) mask. |
[allow.deep]
all = ['C:\Data']
[deny.deep]
write = ['C:\Data\Temp']
The C:\Data grant uses TreeSetNamedSecurityInfoW to recursively propagate inheritable ACEs to all child folders, including \Temp. Sandy then targets \Temp explicitly.
| Pipeline | Action |
|---|---|
| Restricted Token | Places an explicit DENY_ACCESS_ACE (Write) on \Temp. Because Windows evaluates explicit ACEs before inherited ACEs, Deny Write wins over the inherited Allow All. |
| AppContainer | Replaces the DACL on \Temp with the reduced mask (All - Write), but applies it with the PROTECTED_DACL_SECURITY_INFORMATION flag to sever inheritance. This prevents the parent's Allow All from flowing back down and overriding the reduced mask. |
If you specify an allow inside a deny (e.g., Allow on \Temp\Cache), the ACL Pipeline sorts paths by depth and applies them shallow-to-deep. When applying the deepest allow, it actively scrubs inherited sandbox deny/reduced ACEs off the target subtree to ensure the allow rule wins definitively over the parent deny.
Because Sandy leverages the native Windows Security Model, the sandbox has no background daemon and requires meticulous environment restoration after execution.
When the sandbox process finishes normally (exit code 0), Sandy meticulously unwinds all isolation state via a specialized RAII Pipeline.
What happens if the power dies, or a user runs taskkill /f /im sandy.exe? The RAII cleanup is completely bypassed.
sandy.exe --cleanup performs the same recovery work on demand: remove orphaned run ACLs, loopback state, scheduled tasks, and transient AppContainer profiles while preserving live runs and durable saved profiles.--cleanup. Sandy deletes its own task on clean exit; if the process or machine dies unexpectedly, the task provides a later self-healing path on the next logon.For further understanding of the Windows Security Model, consult the official documentation: