Evaluating Windows Security Frameworks as Infrastructure for Agentic Orchestration
Scope: this piece is about local agentic orchestration: an orchestrator,
its tools, and either a local model or a local execution layer for a cloud
model's decisions, all running on the same Windows machine someone controls.
·
In scope: the primitives an orchestrator can call into
or run under to contain its own tool execution, with no kernel driver required.
·
Out of scope, by design, not oversight: a fully remote pipeline where the
orchestrator, the model, and the tools all run as someone else's cloud API.
Windows-level containment isn't even an available lever there.
·
Also out of scope, by design: WFP, minifilter drivers, TDI/NDIS filters, and
PnP filters. Those are how a security vendor builds a kernel driver that
polices every other process on the box (a different threat model, watching
untrusted processes from outside, and a different deployment model, a signed,
WHQL-certified driver, not application code).
Executive Summary
· The problem: most agent frameworks run planning, tool
execution, and credentials in one unmediated process. Even where MCP splits the
process, the split is rarely a security boundary.
· The approach: nine Windows-native containment mechanisms
(VBS Enclaves, Chromium-style and AppContainer sandboxing, Windows Sandbox,
eBPF for Windows, ETW, WDAC/AppLocker, AMSI, and ProjFS/CfApi), evaluated
against one rubric, composed into a reference architecture, then
pressure-tested with an ATAM pass.
· The conclusion: no single mechanism wins. The honest answer is
a risk-tiered mix: an allow-list gate and a secrets enclave as hard,
independent gates, then process-level or VM-level containment depending on how
well-scoped the code being run is.
· The caveat: this is inference from primitives built for
browsers and macros, not agents. It's unvalidated as a reference
implementation, untested at agent-invocation latency, and does nothing against
prompt injection itself, only against what a manipulated decision can do once
it's made.
Most agent orchestration frameworks run tool-execution code in the
same process as the planning loop, sharing its credentials, with no OS-level
boundary between deciding and doing:
·
LangGraph, CrewAI: tool calls are direct in-process Python
function calls by default. No sandbox exists unless a developer bolts one on
separately.
· AutoGen: the same story out of the box
(LocalCommandLineCodeExecutor runs generated code on the host, in AutoGen's own
process). A Docker-based executor exists, but it's opt-in, not what most
deployments ship with.
·
The MCP ecosystem: the one architecture here that actually splits
the tool-execution process from the host. But that split is rarely a security
boundary either. An MCP server typically runs with the same OS-level trust as
any other process the user launches, no restricted token, no job object, no
integrity level gating what it can touch.
Whichever side of a process boundary the tool-execution code lands
on, the underlying problem is identical: an unpredictable decision translates
directly into unmediated OS access. There is no boundary between deciding and
doing, only whatever an engineer built by hand.
Figure 1. LangGraph and CrewAI never split the process;
AutoGen doesn't either unless a developer opts into the Docker executor; MCP is
the one ecosystem that splits the process by design, but the split is a process
boundary, not a security boundary.
Windows has spent over two decades solving a structurally identical
problem for a different class of untrusted code:
·
A browser rendering an
arbitrary web page.
·
A script host executing a macro
from an email attachment.
·
A third-party security engine
that needs to inspect but never fully control the OS.
The primitives that came out of that work were not built with agents
in mind:
·
Process-level sandboxing.
·
Virtualization-based secure
enclaves.
·
Brokered telemetry.
·
Verified-bytecode extension
points.
But the problem they solve is the one agentic orchestration mostly
ignores: contain code whose behavior you can't predict, without trusting it to
police itself.
This article evaluates that stack against one question per
framework: which quality attribute of agent orchestration it serves, and what
it doesn't help with at all. The stack: VBS Enclaves, Chromium-style
broker/target sandboxing (and Windows' own AppContainer/LPAC), Windows Sandbox,
eBPF for Windows, ETW, WDAC/AppLocker, AMSI, and ProjFS/CfApi.
What's Actually at Risk
Before the survey, here is the data flow this article keeps coming
back to, and a STRIDE pass over it. Every threat below is answered by something
later in this article. Nothing here is invented to make the diagram look
complete.
Figure 2. Every arrow in this diagram crosses zero mediated
boundaries in the default architecture. The rest of this article is, in effect,
a catalog of where a boundary could go.
|
STRIDE |
Applies To |
Threat Here |
Addressed Later By |
|
Spoofing |
Planning Loop's inputs |
A tool result or retrieved memory entry impersonates a legitimate
instruction |
Not solved by OS containment; needs input-provenance checks
outside this article's scope |
|
Tampering |
Local Memory / Context Store |
Attacker-writable local state is read back into context on a later
run, becoming persistent poisoned instructions |
ProjFS/CfApi narrows what's writable; doesn't validate content
integrity |
|
Repudiation |
Tool Execution |
No brokered, tamper-resistant record of what a tool call did at
the OS level |
ETW |
|
Information Disclosure |
Credentials / API Keys |
Same-process execution gives a successful prompt injection direct
memory access to whatever credentials the process holds |
VBS Enclave (verdict/ciphertext only), AppContainer/LPAC |
|
Denial of Service |
Tool Execution |
Unbounded resource consumption from a single unsandboxed process |
Job objects (Chromium-style sandbox, Windows Sandbox) |
|
Elevation of Privilege |
Tool Execution → OS |
A model's decision becomes OS-level action with no capability
check narrower than the process's own token |
WDAC/AppLocker, restricted token + integrity level |
Spoofing is the one row nothing downstream fixes. It's a reminder
that OS-level containment bounds what a bad decision can do, not whether the
decision was manipulated in the first place; that's still the orchestrator's
own tool-call policy's job, not the OS's.
The Rubric
These frameworks solve different problems, and it's easy to reach
for the wrong one. Four questions, asked of every entry below:
·
What does it isolate: Code execution, secrets and credentials,
telemetry, or a policy decision?
·
What's the adversary model: A compromised host attacking a trusted
computation, or hostile/unpredictable guest code attacking the host?
·
Where does the logic run: Inside the isolation boundary, or outside it
with only a verdict crossing the line?
·
What's the practical cost: Signing or certification requirements, tooling
maturity, latency per decision, and how much capability you give up to get the
isolation?
Figure 3. The default shape of most agent orchestration
today: no containment boundary, only whatever discipline an engineer imposed by
hand.
The Taxonomy
|
Framework |
Isolates |
Adversary model |
Where the logic runs |
Practical cost |
|
VBS Enclaves |
Secrets, keys, sensitive computation (VTL1) |
Compromised host (even kernel/admin) attacking a trusted secret |
Inside the enclave, but with no network, file I/O, or dynamic
loading |
Trusted Signing certificate; near-zero general capability |
|
Chromium-style broker/target sandbox |
Arbitrary code execution |
Hostile/unpredictable guest code attacking the host |
Outside; target process is fully contained, broker holds every
decision |
User-mode only, no signing cert; ongoing policy-authoring cost |
|
AppContainer / LPAC |
Code execution, capability-scoped |
Same as above, finer-grained |
Outside, with named capability grants (lpacCom, registryRead, …) |
OS-native, no custom broker/target plumbing needed |
|
Windows Sandbox |
Whole-OS execution |
Untrusted, unpredictable code |
Inside an ephemeral VM (HCS-managed Hyper-V container) |
Seconds of spin-up, VM-level resource cost per session; sibling
WDAG is deprecated/removed on 24H2+ |
|
eBPF for Windows |
A narrow, verified slice of vendor logic at a fixed hook |
Buggy or malicious vendor bytecode, verified before it loads |
Inside, for network and process-lifecycle hooks; file-system hooks
remain proposal-only |
Mature for network hooks; process create/delete hook (with veto)
ships via the separate ntosebpfext repo |
|
ETW |
Telemetry stream |
None; it's an observation channel, not an enforcement point |
N/A; fire-and-forget instrumentation |
Low; brokered by the OS, tamper-resistant by session ACL |
|
WDAC / AppLocker |
What's allowed to execute at all |
Anything not on an explicitly signed allow-list |
Outside; vendor supplies data (policy), never code, at the choke
point |
Policy authoring and signing; near-zero runtime cost |
|
AMSI |
Script/buffer content, pre-execution |
Malicious content passed to a script host |
Outside; pure user-mode API call, no kernel component |
Lowest cost on this list; only covers script-host paths |
|
ProjFS / CfApi |
A virtual filesystem namespace, scoped to a provisioned root |
A tool that shouldn't see or touch the real filesystem outside
that root |
Outside; Microsoft's own minifilter relays to a user-mode provider |
No custom minifilter/altitude needed; provider DLL only; covers
nothing outside the root |
|
WHP / HCS |
Not extensibility; the virtualization substrate itself |
N/A (infrastructure layer) |
N/A |
Only relevant if building a bespoke VM tier |
Figure 4. Recast along the rubric's third question: only
three of the ten entries let vendor or agent logic execute inside the boundary
itself. The rest are deliberately built to keep logic outside and let only a
verdict cross the line.
Deep Dives
VBS Enclaves: A Secrets Vault, Not a Runtime
VBS enclaves isolate a software-based trusted execution environment
(VTL1, Hyper-V-backed) from the normal OS (VTL0), strong enough that even a
compromised kernel or admin account cannot read enclave memory. VTL1 itself has
two layers: the kernel-mode Secure Kernel (securekernel.exe), which manages VTL
transitions and validates code signatures, and Isolated User Mode (IUM) running
under it, where Trustlets (LsaIso.exe for Credential Guard, BioIso.exe for
Windows Hello) and VBS enclaves execute. An enclave is IUM user-mode code, not
part of the Secure Kernel itself; it gets no kernel privileges of its own, only
the isolation the hypervisor enforces between VTL0 and VTL1. That same
isolation disqualifies enclaves from running an agent:
·
No network sockets, no file
I/O, no dynamic code loading from inside the boundary.
·
Production code must be signed
via Microsoft's Trusted Signing service before it loads.
The right role for an enclave in an agentic architecture is narrow
and specific: a vault for API keys, signing keys for audit attestation, or a
policy verdict function, called into by an orchestrator that does everything
else outside it.
Figure 5. The enclave runs as IUM user-mode code supervised
by the kernel-mode Secure Kernel, not as part of the kernel itself; nothing
crosses the VTL0/VTL1 boundary except explicit data copies, no shared memory or
pointer the host side can dereference.
Chromium-Style Broker/Target Sandboxing: The Strongest Fit
for Code Containment
Chromium's renderer sandbox is a two-process design:
·
Broker: holds every credential and makes every access
decision.
·
Target: runs the untrusted code under a token stripped
of nearly every privilege, inside a job object that forbids child-process
creation and desktop interaction, at Untrusted integrity level
(SECURITY_MANDATORY_UNTRUSTED_RID, one level below Low).
The broker intercepts the target's resource-touching operations
(file opens, registry access, process creation, named pipes, synchronization
objects) and forwards each to the policy engine before allowing it to happen.
Everything else the target might attempt is denied outright by the restricted
token, job object, and integrity level below it, with no broker round trip
involved. Process mitigations layer on top:
·
Arbitrary Code Guard (ACG): blocks the sandboxed process from generating
and executing new code pages at runtime.
·
Code Integrity Guard (CIG): ensures only Microsoft-signed modules load,
not merely any validly signed binary.
Figure 6. The target cannot act on the host unilaterally;
every call is a round trip through the broker's policy engine. This is the
shape a code-execution tool for an agent should take.
This maps directly onto the standing rule that safety constraints
belong at the permission/credential layer, enforced outside the agent's own
process; the broker isn't asking the target to behave, it structurally cannot
do otherwise, because the broker holds everything the target would need to
misbehave with.
AppContainer / LPAC: The Same Idea, Capability-Scoped
AppContainer/LPAC (Less Privileged App Container) is the OS-native
evolution of the restricted-token approach: instead of a near-total denial, a
process gets a Low Box token with specific named capabilities (lpacCom,
registryRead, lpacWebPlatform, lpacClipboard, …) explicitly granted. For an
agent tool that needs some defined slice of capability (read-only registry
access, clipboard, one specific COM interface), this is a better fit than a
hand-rolled restricted token, without building a full Chromium-style
broker/target plumbing from scratch.
Windows Sandbox: When Process-Level Isolation Isn't Enough
Windows Sandbox runs the untrusted workload inside a genuine
ephemeral virtual machine, not a token/ACL scheme inside a shared kernel. It's
a lightweight Hyper-V container (Microsoft's internal name for the tech is
“Krypton”), provisioned through the Host Compute Service and backed by the
Microsoft hypervisor. The isolation boundary is the hypervisor, not a policy
the kernel enforces on itself.
·
Use it when the code an agent is about to run is unknown,
an agent-authored script executing against untrusted input, for instance,
rather than a routine, well-scoped tool call.
·
Cost: seconds of VM spin-up plus per-session
resource overhead, real enough to make this the wrong default for every tool
call, and the right one for the minority that are high-risk.
Its sibling, Windows Defender Application Guard (WDAG), is not a
live option to weigh against it: Microsoft deprecated Application Guard for
Office in November 2023, and as of Windows 11 24H2, Application Guard for Edge
(including the Isolated App Launcher APIs) is no longer available at all.
Microsoft's own guidance now points organizations needing container-based
isolation to Windows Sandbox instead.
eBPF for Windows: Verified Bytecode, and Now a Process
Hook
eBPF for Windows loads statically-verified bytecode at a fixed
kernel hook. The PREVAIL verifier itself runs in a user-mode protected process,
not in-kernel, so a verifier bug crashes a service, not the OS. That's a
direct, structural contrast with the class of incident that took down
CrowdStrike-affected machines in July 2024. Architecturally, it's the closest
thing on this list to letting a constrained slice of an agent's or vendor's own
logic run with kernel-adjacent visibility, rather than returning a verdict from
outside.
The hook categories, by maturity:
·
Network (shipped, mature): bind, XDP/WFP-L2, cgroup connect, in the core
ebpf-for-windows tree.
·
Process lifecycle (shipped): BPF_PROG_TYPE_PROCESS hooks
PsSetCreateProcessNotifyRoutineEx for process creation and deletion; a verified
program can return a failure NTSTATUS to deny the launch outright, not just
observe it. Ships through a separate, actively maintained Microsoft repo,
ntosebpfext, not the core tree, so adopting it means a two-repo dependency.
·
File system (proposal only): no program type has shipped yet.
For an agent orchestrator, the process hook is directly relevant to
tool-call gating; the still-missing file-system hook leaves data-exfiltration
paths uncovered by this mechanism alone.
ETW: The Audit Trail, Never the Enforcement
ETW is a brokered telemetry stream with three deliberately decoupled
roles: provider (emits events), controller (creates sessions, enables
providers), consumer (reads the stream). A session is the buffered channel
connecting them, not a fourth independent actor. Nothing a provider does can
intercept, block, or modify anything; a provider firing an event is
fire-and-forget instrumentation, full stop.
·
What it's for: a tamper-resistant record of what a sandboxed
tool call did at the OS level, correlated against what the orchestrator
authorized, for post-incident reconstruction.
·
What it isn't: a policy gate. It was built to be incapable of
acting as one.
WDAC / AppLocker: The One That Maps onto the Standing Rule
WDAC and AppLocker both gate execution at a Microsoft-owned choke
point, but split responsibility differently:
·
WDAC: evaluates every PE image at a single choke
point (ci.dll in the image-load path).
·
AppLocker: a kernel-mode Application Identity component
computes file attributes and evaluates policy on process creation and DLL load;
the same component runs in user mode when a script host calls it to verify a
script before running it.
In both cases, the vendor or operator never adds executable logic at
the enforcement point: only declarative data, a signed policy or a rule set,
that existing OS logic evaluates. This is the closest real-world implementation
of “the constraint has to be enforced outside the agent's own process model”: a
WDAC or AppLocker policy is independent of the orchestrator's judgment by
construction. A compromised orchestrator cannot talk its way past it, because
the orchestrator was never the thing making that decision.
AMSI: Content Inspection at the Last Honest Moment
AMSI is the one entry with zero kernel component: a pure user-mode
API (amsi.dll) that script hosts (PowerShell, VBA, .NET dynamic-eval paths)
call before executing a buffer, submitting it to whatever engine is registered
as the provider. It matters the moment an agent's output reaches a script host:
an agent that generates and then executes its own script content is
functionally the same case AMSI already defends against for a malicious macro.
ProjFS / CfApi: A Provisioned Virtual Workspace, Not a
Filesystem-Wide Mediation Layer
ProjFS (prjflt.sys) and the Cloud Files API (cldflt.sys) are
Microsoft's own minifilters at a fixed altitude, exposing pre/post
file-operation callbacks to a user-mode provider (populate this placeholder,
deny this delete) instead of granting a third party its own minifilter and
altitude allocation.
·
Scope is narrow by design: a
provider must explicitly designate a virtualization root
(PrjMarkDirectoryAsPlaceholder followed by PrjStartVirtualizing) before any
interception happens.
·
Only paths inside that root are
projected; everything outside it is invisible to ProjFS entirely.
That makes it the right tool for giving a sandboxed agent tool a
purpose-built, on-demand workspace, a project directory the provider populates
and gates file-by-file, not a general mediation layer over wherever the agent's
tool calls happen to touch on disk. Anything outside the virtualization root
still needs the sandbox's own file-access policy (Chromium's AddRule(), for
instance) or has to be unreachable from the target process in the first place.
WHP / HCS: The Substrate, Not a Framework
Windows Hypervisor Platform and Host Compute Service are what
Windows Sandbox, WSL2, and Hyper-V-backed container runtimes sit on. Not an
extensibility model in the sense of anything else on this list: only relevant
if the right answer for a given agent workload is a bespoke VM-based execution
tier rather than Windows Sandbox as shipped.
A Reference Architecture
Composing the pieces that fit the agent-orchestration problem,
rather than every entry in the taxonomy:
Figure 7. The orchestrator never runs untrusted code itself,
never holds a secret it can't get from the enclave on demand, and never gets to
be the only thing standing between agent-generated code and the host.
One thing the diagram compresses: the ProjFS/CfApi box only covers a
virtualization root the orchestrator provisions ahead of time, typically the
agent's working directory. Paths outside that root aren't virtualized at all;
they're either denied by the sandbox's own file-access rules or unreachable
from the target process to begin with. ProjFS gives the agent a mediated,
on-demand workspace, not a system-wide filesystem interception layer.
Figure 8. Two independent gates, WDAC's allow-list and AMSI's
content check, sit outside the orchestrator's own reasoning, on purpose.
Neither can be argued with by a compromised agent.
An ATAM Pass
ATAM (Architecture Tradeoff Analysis Method) is a structured way of
evaluating whether a proposed architecture satisfies the quality attributes
it's supposed to, developed at the SEI for exactly this kind of problem: a
composition of independently-designed pieces, not a system built from scratch.
It runs in a fixed sequence:
·
Rank the quality attributes
that matter into a utility tree.
·
Trace each one through the
architecture and assess whether it's satisfied.
·
Surface sensitivity points: places where a small change to one part of the
design swings a single quality attribute sharply.
·
Surface tradeoff points: decisions that pull two or more quality
attributes in opposite directions.
·
Close with an explicit list of
risks (attributes that may end up unsatisfied) and non-risks (decisions already
validated elsewhere).
Applied here:
Quality attribute utility tree, ranked:
·
Containment: Can hostile or buggy agent-generated code
affect the host beyond its sandbox.
·
Secrecy: Can a compromised orchestrator host recover
credentials the agent used.
·
Auditability: Can the actual sequence of events be
reconstructed independent of the orchestrator's own account of what happened.
·
Latency: Cost per tool call, not per process launch.
·
Development and certification cost: Signing requirements, tooling maturity.
Sensitivity point (a small change here moves one attribute sharply):
the interception/policy layer. Every framework here that enforces anything
(Chromium's AddRule(), a WDAC policy, an AppLocker rule, a sandbox capability
grant) shares one property: every new tool capability the agent needs is a
policy change at this layer. It scales with agent capability, not agent count,
the same 20-year operational tax Chromium itself still carries.
Tradeoff point (one decision, multiple attributes pulled in opposite
directions): isolation strength against iteration speed and functional
capability. VBS enclaves sit at one extreme: strongest secrecy guarantee,
weakest general capability, no network or file I/O at all. A flat, unsandboxed
agent process sits at the other: fastest to build, zero containment. Everything
surveyed here sits somewhere on that line, and the honest answer to “which one
should I use” is a risk-tiered mix, not a single winner.
Figure 9. The risk-tiered mix from the tradeoff point above,
as an actual decision path. The allow-list and the enclave are hard gates;
everything after them is a matter of degree.
Risks:
·
No public evidence any agent
orchestration framework has assembled this stack into a reference
implementation. This is inference from primitives built for other purposes, not
a validated pattern; treat it as a starting architecture to pressure-test, not a
proven one.
·
Per-tool-call latency, at agent
invocation rates that can run many times a second, is a different design point
than AppLocker's per-process-launch rate (an RPC round trip per launch) or a
browser's per-navigation rate. Nothing here has been load-tested at that
granularity.
·
None of these frameworks were
designed against prompt injection or agent-specific manipulation: they contain
what code can do, not what an LLM can be tricked into deciding to do. The
orchestrator's own tool-call policy still has to do that job; the sandbox only
bounds the blast radius once a bad decision has already been made.
Non-risk: two decades of production hardening against a comparably
hostile input class, arbitrary web content, already validate containment via
broker/target plus job object plus integrity level. This isn't a novel security
model for agents; it's a proven one, pointed at a new kind of untrusted input.
Pre-Deployment Checklist
☐ Is agent-generated or
tool-execution code running in a process boundary distinct from the
orchestrator that holds credentials?
☐ Is there an independent,
declarative allow-list (WDAC/AppLocker) gating what can execute at all,
separate from the orchestrator's own judgment?
☐ Are secrets and credentials
the agent needs held somewhere a compromised orchestrator host cannot read
outright, not just somewhere “the agent doesn't normally look”?
☐ Is every tool call's actual
OS-level behavior logged via a brokered, tamper-resistant channel (ETW),
correlated against what the orchestrator authorized?
☐ Does the sandbox tier match
the risk tier: process-level containment for routine tool calls, VM-level
(Windows Sandbox) for untrusted, agent-authored code?
☐ Is there a
content-inspection point (AMSI) before any agent output reaches a script host?
☐ Has the interception/policy
layer been budgeted as an ongoing cost, not a one-time build, given that every
new tool capability is a new rule?
☐ Has the orchestrator's own
tool-call policy been treated as the thing that stops a bad decision,
separately from the sandbox that only bounds a bad decision's blast radius?
None of this replaces the orchestration-level discipline (bounded
execution, independent verification, circuit breakers outside the loop) that
agentic systems need regardless of what OS they run on. What it adds is a
host-level containment boundary underneath that discipline, built by people who
spent twenty years hardening it against a different kind of untrusted code, so
the orchestrator's judgment isn't the only thing standing between an agent's
decision and the machine it runs on. (For cross-platform tool execution,
WebAssembly's capability-based sandboxing is the closest analog to
AppContainer/LPAC's model, enforced a layer up the stack instead of by the OS.)
Sources
·
Virtualization-based security
(VBS) enclaves - Microsoft Learn
·
VBS Enclaves Development Guide
- Microsoft Learn
·
Chromium Windows sandbox design
document
·
eBPF for Windows -
microsoft/ebpf-for-windows (GitHub)
·
NTOS eBPF Extension (process
create/delete hook) - microsoft/ntosebpfext (GitHub)
·
Defender for Endpoint on Linux:
eBPF-based Auditd replacement - Microsoft Learn
·
The Windows Resiliency
Initiative - Windows Experience Blog (Microsoft)
No comments:
Post a Comment