You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[BUG] workspace-write provisioning permanently relabels the workspace root to Low integrity — breaks every toolchain built from that workspace, outside DSH, across sessions and reboots, with no restore path and no audit trail
#11833
Windows 11 24H2, 10.0.26100.3775, zh-CN, single local admin account (UAC-filtered)
Workspace: <workspace> (Flutter 3.47.7 / Dart 3.13.5, Windows desktop target)
Sandbox mode in the affected sessions: workspace-write
Paths are anonymized below: <workspace> = the affected project directory, <user> = the Windows profile name, <app> = the application binary.
TL;DR
workspace-write provisioning writes a Low mandatory integrity label onto the workspace root (one SetNamedSecurityInfoW call that also adds the Everyone
delete-child deny and the OWNER RIGHTS grant). The label is never reverted — not on
provider dispose, not on session end, not on reboot, not on uninstall.
Consequence: every executable built or launched from that workspace inherits Low IL,
and Low IL cannot write to Medium-IL %LOCALAPPDATA%\Temp or %APPDATA%. The damage is
therefore not confined to the sandbox: after all DSH sessions are closed, the user's
own terminal, IDE, build scripts, test runners and installers fail with EACCES
(errno 5) on paths that have nothing to do with DSH.
This is strictly more severe than #9314: #9314 describes sandboxed writes failing.
What we measured is a persistent, machine-wide breakage of the developer's toolchain
caused by DSH, that survives DSH, and that the user cannot repair in place.
User-visible symptom
flutter run -d windows, launched from a normal (non-DSH) terminal:
Oops; flutter has exited unexpectedly: "_createDevFS: (-32603) Internal error
_createDevFS: Unexpected exception:PathAccessException: Creation of temporary directory
failed, path = 'C:\Users\<user>\AppData\Local\Temp' (OS Error: Access is denied., errno = 5)
#1 _Directory.createTemp.<anonymous closure> (dart:io/directory_impl.dart:163:7)
#2 createTempDirCallback (dart:vmservice_io:118:16)
#3 DevFS._createDevFS (dart:_vmservice/devfs.dart:197:21)
Window preferences could not be saved: PathAccessException: Cannot open file,
path = 'C:\Users\<user>\AppData\Roaming\com.example.<app>\<app>\window.json'
(OS Error: Access is denied., errno = 5)
Reproduced 7 times over two hours (flutter_01.log … flutter_07.log). The workspace is
completely undevelopable: hot reload cannot start, and the app cannot persist settings.
The stack trace points at dart:io, so it reads like a Flutter or Dart bug.
Root cause
<workspace> carries an explicit Low integrity label with inheritance:
It is inherited by everything created afterwards — build\, .dart_tool\, regenerated
root files — while files that predate the labeling stay unlabeled, so the tree looks
inconsistent and the root is the only obvious anomaly.
Because a process's integrity level is capped by the label of the image it is launched
from, build\windows\x64\runner\Debug\<app>.exe runs at Low:
Process
Token integrity
mkdir %TEMP%\probe
<app>.exe from <workspace>\build\...
S-1-16-4096Low
❌ EACCES
same binary copied to %TEMP% / Desktop / drive root
S-1-16-8192 Medium
✅
same binary in %TEMP%, -WorkingDirectory <workspace>
S-1-16-8192 Medium
✅ (so it is the file label, not the CWD)
cmd.exe copied into the workspace
S-1-16-4096Low
❌ EACCES
cmd.exe from System32
S-1-16-8192 Medium
✅
The last two rows isolate the mechanism: it is the integrity label on the image file, and
Low IL is sufficient by itself to produce errno 5 on %TEMP%.
<workspace> also carries the two other edits described by the provisioning code, which
is how we matched the fingerprint:
Code evidence from the shipped app.asar (string scan of the archive):
"…is the only delete authority inside the granted roots, and labels the same
directory Low in the one SetNamedSecurityInfoW call that applies all three edits."
and, for teardown:
workspaceGrants … "one private-temp grant per live session/workspace pair
(revoked on provider dispose)"
The DACL grants are revoked on dispose. The integrity label has no restore path at all:
The damage escapes the sandbox. It persists with zero DSH processes running, and
breaks the user's normal dev loop in any terminal, IDE or CI script.
Blast radius is every executable in the tree, not DSH's own commands: Flutter/Dart
tooling, CMake/MSBuild output, test runners, Node scripts, packaging and signing steps,
installers. Any of them that touches %TEMP% or %APPDATA% fails — usually with a
stack trace that blames the wrong component.
Not repairable in place by the user. Even as the file owner, icacls <file> /setintegritylevel Medium returns Access is denied — raising a label
requires WRITE_OWNER / SeRelabelPrivilege, which the inherited ACEs do not grant.
The only non-elevated route is to delete and regenerate build outputs (a full
rebuild for a large workspace), or to run an elevated /T pass over the whole tree.
Re-cloning does not help. The label lives on the directory object. Cloning the
repo again into the same path re-inherits Low for every new file.
It looks exactly like a permissions bug but is not. ACLs are genuinely correct:
the user's SID has full control on %LOCALAPPDATA%\Temp, the user is the owner, there
are no deny ACEs, and a Medium-IL process writes there without complaint. Every
conventional check — icacls, Get-Acl, Explorer's Security tab, "take ownership" —
reports "permissions are fine". Get-Acl cannot even show the problem, because reading
the SACL requires SeSecurityPrivilege.
No warning, no audit trail, no breadcrumb. Nothing is logged when the workspace
security descriptor is modified; no event log entry, and nothing in the session
transcript. Session bodies are stored as session.v4.jsonl.zstd, so even after
un-archiving every session of the workspace there is no way to attribute the change to
a session. We could not identify which session did it, and that is itself a defect.
The built-in diagnostic dead-ends. The bundled diagnose-windows-sandbox-acl skill
does detect this state ($LOW_LABEL_SID = 'S-1-16-4096' → $facts.LowLabel = $true),
but by design it never removes a label or a deny ACE, and it offers no remedy — so the
one tool that can see the problem reports it and stops.
Security posture is inverted. The workspace is left writable by Low-IL processes
and not writable by the signed-in user's own Medium-IL tooling — the opposite of the
intended boundary, permanently, on a source tree.
Minimal repro
Open a workspace in DSH with sandbox mode workspace-write; run any command
(echo hi is enough) so provisioning runs.
Build any executable inside the workspace, launch it, and read its token: TokenIntegrityLevel → S-1-16-4096 (Low).
That executable now fails every write to %LOCALAPPDATA%\Temp and %APPDATA%
with errno 5, with no DSH process anywhere on the machine.
Suggested fix
Do not label the workspace root. Give the sandboxed token write access through the
DACL only, or route its writable scratch space to a dedicated subtree (e.g. <workspace>\.dsh-tmp) and label that Low — never the root that users build in.
If the root must be labeled: capture the pre-provisioning security descriptor and
restore it verbatim on dispose — label and both added ACEs — and journal it so a
killed or crashed session still restores on next start.
Self-check on startup: if the workspace root has a Low label, warn and offer repair.
Let diagnose-windows-sandbox-acl repair the label it already detects, instead of
reporting and stopping.
Record provisioning in the audit trail (event log and/or session transcript) with
the before/after descriptor, so the change can be attributed.
Workaround for affected users (verified)
# 1. detect
icacls "<workspace>"| findstr "Mandatory Label"# 2. raise the root, if you hold Full Control on it (no elevation needed)
icacls "<workspace>"/setintegritylevel (OI)(CI)Medium
# 3. inherited children reject step 2 with Access denied — regenerate them insteadRemove-Item"<workspace>\build","<workspace>\.dart_tool"-Recurse -Force
# (for Low-labeled loose files, recreate them byte-exact so they re-inherit Medium)# 4. or, from an elevated shell, do the whole tree in one pass
icacls "<workspace>"/setintegritylevel (OI)(CI)Medium /T /C
Do not "fix" %LOCALAPPDATA%\Temp — its permissions are correct and were never the
problem. Any advice that starts by repairing Temp or %APPDATA% is chasing the symptom.
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
Environment
<dsh-install>(resources/app.asar, ~183 MB)<workspace>(Flutter 3.47.7 / Dart 3.13.5, Windows desktop target)workspace-writeTL;DR
workspace-writeprovisioning writes a Low mandatory integrity label onto theworkspace root (one
SetNamedSecurityInfoWcall that also adds theEveryonedelete-child deny and the OWNER RIGHTS grant). The label is never reverted — not on
provider dispose, not on session end, not on reboot, not on uninstall.
Consequence: every executable built or launched from that workspace inherits Low IL,
and Low IL cannot write to Medium-IL
%LOCALAPPDATA%\Tempor%APPDATA%. The damage istherefore not confined to the sandbox: after all DSH sessions are closed, the user's
own terminal, IDE, build scripts, test runners and installers fail with
EACCES(
errno 5) on paths that have nothing to do with DSH.This is strictly more severe than #9314: #9314 describes sandboxed writes failing.
What we measured is a persistent, machine-wide breakage of the developer's toolchain
caused by DSH, that survives DSH, and that the user cannot repair in place.
User-visible symptom
flutter run -d windows, launched from a normal (non-DSH) terminal:Reproduced 7 times over two hours (
flutter_01.log…flutter_07.log). The workspace iscompletely undevelopable: hot reload cannot start, and the app cannot persist settings.
The stack trace points at
dart:io, so it reads like a Flutter or Dart bug.Root cause
<workspace>carries an explicit Low integrity label with inheritance:It is inherited by everything created afterwards —
build\,.dart_tool\, regeneratedroot files — while files that predate the labeling stay unlabeled, so the tree looks
inconsistent and the root is the only obvious anomaly.
Because a process's integrity level is capped by the label of the image it is launched
from,
build\windows\x64\runner\Debug\<app>.exeruns at Low:mkdir %TEMP%\probe<app>.exefrom<workspace>\build\...S-1-16-4096LowEACCES%TEMP%/ Desktop / drive rootS-1-16-8192Medium%TEMP%,-WorkingDirectory <workspace>S-1-16-8192Mediumcmd.execopied into the workspaceS-1-16-4096LowEACCEScmd.exefromSystem32S-1-16-8192MediumThe last two rows isolate the mechanism: it is the integrity label on the image file, and
Low IL is sufficient by itself to produce
errno 5on%TEMP%.<workspace>also carries the two other edits described by the provisioning code, whichis how we matched the fingerprint:
Code evidence from the shipped
app.asar(string scan of the archive):and, for teardown:
The DACL grants are revoked on dispose. The integrity label has no restore path at all:
So this is not a rare leak on a crashed teardown — there is no code that ever undoes it.
Why this is more severe than #9314
breaks the user's normal dev loop in any terminal, IDE or CI script.
tooling, CMake/MSBuild output, test runners, Node scripts, packaging and signing steps,
installers. Any of them that touches
%TEMP%or%APPDATA%fails — usually with astack trace that blames the wrong component.
icacls <file> /setintegritylevel MediumreturnsAccess is denied— raising a labelrequires
WRITE_OWNER/SeRelabelPrivilege, which the inherited ACEs do not grant.The only non-elevated route is to delete and regenerate build outputs (a full
rebuild for a large workspace), or to run an elevated
/Tpass over the whole tree.repo again into the same path re-inherits Low for every new file.
the user's SID has full control on
%LOCALAPPDATA%\Temp, the user is the owner, thereare no deny ACEs, and a Medium-IL process writes there without complaint. Every
conventional check —
icacls,Get-Acl, Explorer's Security tab, "take ownership" —reports "permissions are fine".
Get-Aclcannot even show the problem, because readingthe SACL requires
SeSecurityPrivilege.security descriptor is modified; no event log entry, and nothing in the session
transcript. Session bodies are stored as
session.v4.jsonl.zstd, so even afterun-archiving every session of the workspace there is no way to attribute the change to
a session. We could not identify which session did it, and that is itself a defect.
diagnose-windows-sandbox-aclskilldoes detect this state (
$LOW_LABEL_SID = 'S-1-16-4096'→$facts.LowLabel = $true),but by design it never removes a label or a deny ACE, and it offers no remedy — so the
one tool that can see the problem reports it and stops.
and not writable by the signed-in user's own Medium-IL tooling — the opposite of the
intended boundary, permanently, on a source tree.
Minimal repro
workspace-write; run any command(
echo hiis enough) so provisioning runs.TokenIntegrityLevel→S-1-16-4096(Low).%LOCALAPPDATA%\Tempand%APPDATA%with
errno 5, with no DSH process anywhere on the machine.Suggested fix
DACL only, or route its writable scratch space to a dedicated subtree (e.g.
<workspace>\.dsh-tmp) and label that Low — never the root that users build in.restore it verbatim on dispose — label and both added ACEs — and journal it so a
killed or crashed session still restores on next start.
diagnose-windows-sandbox-aclrepair the label it already detects, instead ofreporting and stopping.
the before/after descriptor, so the change can be attributed.
Workaround for affected users (verified)
Do not "fix"
%LOCALAPPDATA%\Temp— its permissions are correct and were never theproblem. Any advice that starts by repairing Temp or
%APPDATA%is chasing the symptom.All reactions