summaryrefslogtreecommitdiff
path: root/src/Agent.Windows
diff options
context:
space:
mode:
authortanaka takashi <isazaka@gmail.com>2026-08-13 18:20:33 +0900
committertanaka takashi <isazaka@gmail.com>2026-08-13 18:20:33 +0900
commit76fdcb43585a4c4d288c1026d318a0ddbe3e26ab (patch)
treef58296832d37b035d3e787e0f270c77b59c89d77 /src/Agent.Windows
parent78fe349073e3a2e89f0bf14b134ae0955aa7182a (diff)
fix(sandbox): correct cmd descendant handling and protected ACL policy
Replace the earlier cmd-wide descendant incompatibility diagnosis with the verified distinction between drive-qualified paths and PATH/workspace-relative invocation. Document the cmd YAML configuration, executable resolution, --no-runtime approval flow, and safe descendant invocation examples in the user README. Keep the System32 protected DACL intact for both the OS Runtime Root and approved entry files nested below it. Skip redundant file-level ACL rewrites for approved System32 executables while retaining LPAC confinement, resolved-path checks, SHA-256 approval, WFP policy, and Job Object enforcement. Expand Windows coverage with capability positive/negative matrices, protected-DACL regression tests, cmd/PowerShell/venv Python script execution, nine Entry-to-Descendant combinations, network none/local probes, and randomized ACL round-trip testing. Add read-only CLI/README verification and published HTTP MCP agent_run verification scripts. Update Design, Audit Report, and Requirement Traceability with the corrected root cause, current evidence, withdrawn diagnostic conclusions, and the remaining partial item for per-combination descendant self-recorded LPAC SID/Job evidence. Verified: Release build 0 warnings/errors; Core 103 PASS; Planner 10 PASS; Windows 75 PASS with skip 0; README operational suite 19 PASS; published HTTP MCP agent_run completed 3/3 with cmd, curl, C:\tmp\.venv Python, network-none enforcement, ACL restoration, and CMD_HTTP_MCP_OK.
Diffstat (limited to 'src/Agent.Windows')
-rw-r--r--src/Agent.Windows/Tools/WindowsToolBackend.cs16
1 files changed, 13 insertions, 3 deletions
diff --git a/src/Agent.Windows/Tools/WindowsToolBackend.cs b/src/Agent.Windows/Tools/WindowsToolBackend.cs
index af4c906..ec122e9 100644
--- a/src/Agent.Windows/Tools/WindowsToolBackend.cs
+++ b/src/Agent.Windows/Tools/WindowsToolBackend.cs
@@ -48,6 +48,10 @@ public sealed class WindowsToolBackend(EffectiveSandboxPolicy settings, ISecurit
_taskUpdates.BeginTask(taskId, sessionId);
try
{
+ string[] osRuntimeRoots = settings.Files
+ .Where(static entry => entry.Origin.Split(',').Contains("os_runtime_root", StringComparer.Ordinal))
+ .Select(static entry => ResolvedPath.Resolve(entry.Path, false))
+ .ToArray();
foreach ((string path, FileCapability capabilities, bool osRuntimeRoot) in settings.Files
.GroupBy(static entry => ResolvedPath.Resolve(entry.Path, false), StringComparer.OrdinalIgnoreCase)
.Select(static group => (group.Key,
@@ -57,9 +61,12 @@ public sealed class WindowsToolBackend(EffectiveSandboxPolicy settings, ISecurit
// System32 has a protected OS-owned DACL. Its existing LPAC access is verified by
// real process-tree tests; changing or unprotecting that DACL is forbidden.
if (osRuntimeRoot) continue;
- // OS/runtime executables may already grant AppContainer execute through their protected system ACL.
- // Do not rewrite a file ACL when execute is the only requested capability; CreateProcess remains
- // constrained by LPAC access plus Resolved Path/SHA-256 Entry approval.
+ // Approved System32 Entry files are nested under the same protected OS Runtime Root.
+ // Their existing LPAC access is used; a separate file-level DACL rewrite is forbidden.
+ if (File.Exists(path) && capabilities == (FileCapability.Read | FileCapability.Execute) &&
+ osRuntimeRoots.Any(root => IsBelow(path, root))) continue;
+ // Executable-only entries may already grant AppContainer execute through their system ACL.
+ // CreateProcess remains constrained by LPAC access plus Resolved Path/SHA-256 Entry approval.
if (File.Exists(path) && capabilities == FileCapability.Execute) continue;
// A single inheritable ACE on an approved directory covers existing and newly-created
// descendants. Snapshotting and rewriting every child ACL is both redundant and
@@ -305,6 +312,9 @@ public sealed class WindowsToolBackend(EffectiveSandboxPolicy settings, ISecurit
}
private TaskContext Get(Guid taskId) => _contexts.TryGetValue(taskId, out TaskContext? context) ? context : throw new InvalidOperationException("Task Resource scope is not active.");
+ private static bool IsBelow(string child, string parent) =>
+ child.StartsWith(parent.TrimEnd(Path.DirectorySeparatorChar) + Path.DirectorySeparatorChar,
+ StringComparison.OrdinalIgnoreCase);
private static ToolExecutionResult Success(string output, bool externalEffect = false) => new(true, output, externalEffect);
private static bool IsTextMatch(string path, Func<string, bool> predicate)
{