A lightweight Windows sandbox runner. Run any executable in an isolated, kernel-enforced sandbox with fine-grained file, folder, and network access control — no VMs, no Docker, no elevation required. Features first-class persistent profiles and transient one-shot sandboxes.

Single native executable 🔒 Kernel-enforced isolation 📁 Granular ACL control 🧹 Self-healing cleanup
# Risky operation: cleaning a test folder — one wrong path
# and your entire project is gone. Sandy makes it safe:

sandy.exe -c cleanup.toml -x cmd.exe /c "del /s /q * && rd /s /q ."

# cleanup.toml — only 6 lines needed:
[sandbox]
token = 'appcontainer'
workdir = 'C:\project\test\output'
[allow.deep]
all = ['C:\project\test\output']  # nothing else is reachable
[limit]
timeout = 30

# Everything else defaults to deny-all / disabled.
# Your project, profile, and system files are kernel-protected.

A practical alternative

VMs take minutes to boot. Windows Sandbox needs Hyper-V. OS-level isolation is overkill when you just need to run a quick script safely. While setting large ACL grants takes a moment, Sandy remains a highly practical, native alternative — no bloated runtime, no setup, no VM waiting.

🏢

Works without admin

In locked-down corporate environments, Hyper-V, Windows Sandbox, and even VMs may be disabled by policy — you only own the user domain with no elevation. Sandy runs entirely in user-space using unprivileged Windows APIs. No admin, no GPO exceptions needed.

🛡️

Kernel-enforced boundaries

Sandy doesn't simulate isolation — it leverages the same kernel-level security mechanisms that protect UWP apps and Microsoft Edge. Access decisions are made by the Windows kernel, not by Sandy.

Primary Use Cases

Sandy is built for situations where you need to run code but can't fully trust what it might do to your system.

💥

Risky cleanup operations

Commands like rm -rf *, recursive deletes, or batch file mutations are one typo away from disaster. Sandy constrains the blast radius — the process can only touch paths you explicitly allow.

🤖

Agentic tools & workflows

AI agents that call tools, write files, and execute code need guardrails. Sandy gives each agent invocation its own sandbox with precise permissions — read the project, write to output, deny everything else.

🧠

Autonomous agentic work

Long-running autonomous agents produce unpredictable filesystem activity. Sandy provides durable sandboxing that survives agent crashes, restarts, and multi-hour execution — with full auditability via session logs.

📦

Untrusted applications

Downloaded executables, third-party scripts, npm packages running post-install hooks — run them sandboxed first. Sandy blocks access to your profile, secrets, and system unless explicitly granted.

🔬

Security research & testing

Analyze hostile or fragile executables inside a disposable sandbox, or create durable profiles for repeated investigation with the same constrained identity and grant set.

⚙️

CI/CD & automation pipelines

Run build steps, test suites, and deployment scripts with least-privilege filesystem access. Sandy's TOML configs are version-controllable and its exit codes follow POSIX conventions for clean integration.

How It Works

Sandy reads your TOML configuration, creates an isolated security context, grants precisely the permissions you specify, launches your process, and restores everything on exit.

Execution Pipeline

Phase 1 Setup Create sandbox identity
Phase 2 Grant Apply ACL pipeline
Phase 3 Prepare Build token & env
Phase 4 Launch Start child process
Phase 5 Cleanup Restore all state

Two Isolation Modes

AppContainer AC mode

Uses the same kernel-level isolation as UWP apps and Microsoft Edge. Each instance gets a unique AppContainer SID (S-1-15-2-*) derived from a UUID-based profile name.

  • Isolated object namespace — invisible to other processes
  • Configurable network isolation (internet, LAN, localhost)
  • LPAC mode opts out of App. Packages for stricter default access
  • Private registry hive — no host registry access
  • Deny rules not supported (kernel ignores DENY ACEs for AC SIDs)
Restricted Token RT mode

Creates a restricted token with a unique per-instance SID (S-1-9-*) under the Resource Manager authority. Supports configurable integrity level — low or medium.

  • Real DENY_ACCESS ACEs — kernel evaluates deny-before-allow
  • Named pipe support (Flutter, Chromium, Mojo IPC)
  • COM/RPC server access for complex applications
  • Configurable registry grants ([registry] section)
  • Medium integrity for wider app compatibility
💡 Choosing a mode

Use AppContainer / LPAC when you need network isolation and don't require named pipes or COM.
Use Restricted Token when the sandboxed app needs named pipes, COM/RPC, or medium integrity for broader compatibility.

Per-Instance Isolation

Every Sandy instance generates a UUID at startup and derives a unique SID for all ACL operations. This is the foundation of multi-instance safety:

AspectAC / LPACRestricted Token
Instance SID S-1-15-2-* (from profile name) S-1-9-* (from GUID)
Grant scope Per-instance — isolated ACEs Per-instance — isolated ACEs
Cleanup scope Own ACEs only — zero interference Own ACEs only — zero interference
Registry tracking HKCU\Software\Sandy\Grants\<UUID> HKCU\Software\Sandy\Grants\<UUID>

ACL Management

Sandy manages Windows DACLs at the ACE level — adding individual Access Control Entries on grant, removing them on cleanup. This is fundamentally different from snapshot-based DACL restoration, which races fatally with concurrent instances.

Permission Levels

LevelConfig KeyWhat It GrantsKey Restriction
ReadreadRead files, list directoriesNo FILE_EXECUTE — can't load DLLs
WritewriteCreate and modify filesNo read — write-blind
ExecuteexecuteRead + executeStandard (RX) — for running programs
AppendappendAppend data to filesNo overwrite, no read
DeletedeleteDelete files and directoriesNo read, no write
AllallFull data controlNo WRITE_DAC, WRITE_OWNER, FILE_DELETE_CHILD
RunrunExecute only, no readOS loader can run binary, sandbox can't copy it
StatstatRead attributes onlyCheck existence, size, timestamps
TouchtouchModify attributes onlyNo data read or write
CreatecreateCreate new files/subdirsNo overwrite of existing files
⚠️ Permissions are independent

write does not grant read, and read does not grant execute. Grant each explicitly, or use all. Directories with executables (Python, Node) need execute, not read.

Deny Mechanics — Restricted Token Only

Restricted Token

Uses real DENY_ACCESS ACEs. The Windows kernel evaluates DENY before ALLOW as expected — straightforward and reliable.

AppContainer

The kernel ignores DENY ACEs for AppContainer SIDs. Sandy rejects deny rules for AC mode via allow-mask reduction — reading the existing ALLOW ACE, subtracting the denied bits (preserving shared bits like SYNCHRONIZE), and writing back a reduced mask with PROTECTED_DACL to break inheritance.

Depth-Sorted Pipeline — Allow Inside Deny (Restricted Token)

Sandy supports carving out allowed subtrees from within denied areas. All allow and deny entries are merged into a single pipeline, sorted by path depth. The most specific (deepest) path always wins:

# Config: deny all of C:\repos, but allow C:\repos\snipps
[deny.deep]
all = ['C:\repos']

[allow.deep]
all  = ['C:\repos\snipps']

[allow.this]
stat = ['C:\repos']         # stat the repos dir itself

# Pipeline execution log:
PIPELINE: sorted 3 entries by path depth:
    DENY  [ALL    ] C:\repos
    ALLOW [STAT   ] C:\repos            <- strip deny (dir only)
    ALLOW [ALL    ] C:\repos\snipps     <- strip deny (subtree)

Crash Resilience

Sandy never leaves your system in a dirty state. Every exit path — clean, crash, signal, power loss — has a guaranteed cleanup mechanism.

ScenarioACLsLoopbackContainerTaskRegistryMechanism
Clean exitRAII guard
Child crashChild exit ≠ Sandy exit
Ctrl+C / closeConsole signal handler
Sandy crash (SEH)__except handler
Power loss / taskkillScheduled task at logon
  1. Write-Ahead Logging

    Before modifying any ACL, Sandy persists each grant as TYPE|PATH|SID to HKCU\Software\Sandy\Grants\<UUID>. The registry write happens before the filesystem modification — if Sandy crashes mid-grant, the record survives for later cleanup.

  2. Per-Instance Scheduled Task

    A SandyCleanup_<UUID> task is registered in Task Scheduler, configured to run sandy.exe --cleanup at next logon. It only fires if Sandy didn't clean up normally. Deleted on clean exit.

  3. Dead-PID Detection

    --cleanup checks each persisted PID with OpenProcess + WaitForSingleObject to handle zombie processes (terminated but handle still open). Only entries from truly dead processes are cleaned.

  4. ACE-Level Restoration

    Cleanup walks each stale grant, removes only the ACEs matching the dead instance's SID via RemoveSidFromDacl, and deletes the registry subkey. Live instances' grants are never touched.

✅ Five resources tracked and cleaned

ACL grants · Registry persistence · Loopback exemptions · AppContainer profiles · Scheduled tasks — all automatically restored regardless of exit path.

Safety Guarantees

Sandy's security model is additive and explicit — the sandbox starts with zero access, and every permission is granted individually. Several design decisions enforce defense-in-depth.

🧬

Multi-instance isolation

Concurrent Sandy instances have completely independent SIDs, ACE sets, and registry subkeys. One instance's cleanup never touches another's grants — verified by dedicated concurrent test suites.

🔍

Dry-run validation

--dry-run validates the entire config and shows all planned changes (ACL modifications, capabilities, environment) without touching the system. Run it first to catch mistakes.

🧱

Fail-closed resource limits

If a configured resource limit (memory, process count) cannot be enforced via the job object, Sandy terminates the child immediately with exit code 129. The sandbox never runs with unenforced limits.

📊

Full operational trail

Session logs capture every ACL operation, deny rule application, and error with Win32 error codes. Cleanup and recovery behavior are tracked in the same runtime log, with no extra host-global dump layer to manage.

🚫

Stripped dangerous bits

Even with all access, three bits are permanently excluded: WRITE_DAC (can't modify ACLs), WRITE_OWNER (can't take ownership), FILE_DELETE_CHILD (can't bypass child deny).

🛑 DENY ACE kernel invariant

The Windows kernel does not evaluate DENY_ACCESS ACEs for AppContainer SIDs. This is an immutable property of the OS. Sandy rejects [deny.*] for AppContainer mode at config validation time. Only Restricted Token mode supports deny rules, using real DENY_ACCESS ACEs — the correct approach for each kernel behavior.