dsh-file-integrity-check
DSH runs restricted Windows workspaces under a Low mandatory integrity label so its restricted token can write there. The label and the sandbox's explicit S-1-4-* ACEs live in the directory's on-disk ACL, so they can outlast the session, the workspace removal, and even a DSH update. On directories that remain marked, installers, IDEs, backup tools, and other programs may later fail permission checks or behave unexpectedly.
This plugin gives those directories a controlled cleanup path. It reads the live DSH workspace list (not a disk crawl), scans each workspace without changing anything, reports the exact directories and finding types, repairs only the sandbox residue after confirmation, and verifies the result. Each workspace keeps one replaceable ACL rollback record, so the last repair can be undone or its record permanently deleted.
The three findings it understands:
- Low integrity label on a directory (SACL mandatory label,
S-1-16-4096) - Explicit
S-1-4-*sandbox allow ACEs (non-inherited) Everyone:(DENY)(DC)only when it appears on the same directory as one of the two findings above
It never touches normal workspace grants such as X2\<user>:(F). A standalone
Everyone deny is not a finding and is left alone.
The plugin has a white workspace-mapped page in the DSH sidebar, plus a standalone PowerShell engine that can be used without DSH.
English
Features
- Scan any DSH workspace, or all workspaces at once.
- Fix with an explicit confirmation; a read-only dry run is the default.
- Verify after fixing and show
Low/S-1-4counts. - One rollback record per workspace. The newest successful fix replaces the previous record. A record can be kept indefinitely or permanently deleted; deleting it removes every file and empty folder it owns.
- Workspace mapping comes from DSH's workspace registry. If a workspace is deleted in DSH, its card disappears from the plugin page.
- No third-party dependencies. The engine is Windows PowerShell 5.1 /
PowerShell 7 plus inline C# P/Invoke and
icacls.
Install
From dsh-market
Once the catalog entry is merged, search for 文件完整性检查 / File Integrity Check in dsh-market and click Install.
From source
Clone the repository, then add the directory as a local DSH bundle through the
Plugin Manager (install_bundle). For example, with the DSH agent tool:
plugin_manager action=install_bundle target="<path-to>\dsh-file-integrity-check"
After installation, refresh the DSH web GUI. The sidebar shows a shield icon named 文件完整性检查. If the Host half changed, fully quit and reopen DSH, not just the page.
Use
- Open 文件完整性检查 from the sidebar.
- Each DSH workspace gets one card, read from the live workspace list.
- 扫描 (Scan) is read-only.
- 修复 (Fix) asks for confirmation, saves the current ACL, then changes it.
- 校验 (Verify) rescans and reports the remaining counts.
- 扫描全部工作区 (Scan all) scans every current workspace in one request.
After a successful fix the card shows a 可回滚 (Rollback available) badge. The detail panel shows the record time and path, with 回滚到上次状态 and 删除记录. The latter asks for confirmation and permanently deletes the record directory.
How it works
- The mandatory label is read via
GetNamedSecurityInfoWwithLABEL_SECURITY_INFORMATIONand theSYSTEM_MANDATORY_LABEL_ACE(type0x11). The last SID sub-authority is0x1000for Low and0x2000for Medium. - The DACL is read through the same API. Only non-inherited ACEs whose SID
authority is 4 (
S-1-4-*) are removed.Everyonedeny ACEs are removed only when the same directory is already a Low/S-1-4 finding. - The root label is restored with an inheritable Medium label
(
icacls /setintegritylevel "(OI)(CI)M"). If a child has an explicit Low label, it is fixed individually. - The original DACL is stored as SDDL plus an
icacls /save.aclfile. The rollback record containsmanifest.json,root.acl, androot.sddl. - Reparse points and junctions are never followed. Long paths use the
\\?\prefix. Heavy directories such asnode_modules,.git,dist,.venv, andAppData\Local\Tempare skipped.
Rollback records
%LOCALAPPDATA%\dsh-lowlabel-fix\rollback\<first-16-hex-of-path-sha256>\
Each record contains only ACL metadata, not file contents. A successful fix for
the same workspace replaces that directory atomically. Deleting a record
removes the directory and any empty rollback / dsh-lowlabel-fix parents.
A workspace with no findings produces no backup and no record at all.
CLI
# Scan one workspace tree
powershell -NoProfile -ExecutionPolicy Bypass -File .\scripts\DshWorkspaceAcl.ps1 `
-Action scan -Path "D:\project" -Deep
# Fix (dry run unless -Apply is present)
powershell -NoProfile -ExecutionPolicy Bypass -File .\scripts\DshWorkspaceAcl.ps1 `
-Action fix -Path "D:\project" -Apply
# Verify
powershell -NoProfile -ExecutionPolicy Bypass -File .\scripts\DshWorkspaceAcl.ps1 `
-Action verify -Path "D:\project"
# List rollback records
powershell -NoProfile -ExecutionPolicy Bypass -File .\scripts\DshWorkspaceAcl.ps1 `
-Action records
# Roll back one workspace
powershell -NoProfile -ExecutionPolicy Bypass -File .\scripts\DshWorkspaceAcl.ps1 `
-Action rollback -Path "D:\project"
# Permanently delete one record
powershell -NoProfile -ExecutionPolicy Bypass -File .\scripts\DshWorkspaceAcl.ps1 `
-Action delete-record -Path "D:\project"
-Json writes machine-readable output to stdout; progress and stage messages
go to stderr.
Safety
- Only non-inherited
S-1-4-*allow ACEs are removed. Everyone:(DENY)(DC)is removed only on a directory that also has a Low or S-1-4 finding.- Only Low labels are restored to Medium.
- Junction points and reparse points are skipped.
- ACLs are saved before any change.
- Unreadable directories are reported and skipped; the rest of the batch continues.
- No administrator rights are required for directories owned by the current user. Protected system locations may still be unreadable or unwritable; those are reported, not forced.
Requirements
- Windows 10 or Windows 11
- DSH 0.2.1 or newer (desktop or web)
- Windows PowerShell 5.1 or PowerShell 7
Project layout
index.js Host half: HTTP route + PowerShell runner
client.js Client half: sidebar entry + workspace page
cordis.patch.yml DSH bundle patch
scripts/DshWorkspaceAcl.ps1 Standalone scan/fix/verify/rollback engine
locale/ UI strings
marketplace/ dsh-market catalog entry and submission notes
Development
The PowerShell script is intentionally UTF-8 with BOM; Windows PowerShell 5.1 needs the BOM to parse the Chinese messages correctly. When editing it, re-add the BOM if your editor removes it.
There is no build step and no node_modules requirement.
License
MIT. See LICENSE.
中文
DSH 在 Windows 上运行受限工作区时,会把目录的完整性级别降到 Low,并写入显式的 S-1-4-* 沙箱授权 ACE,让受限令牌可以写入。这些标记保存在目录的磁盘 ACL 里,会话结束、工作区从 DSH 移除、甚至 DSH 升级之后都可能继续存在。长期保持标记的目录,可能让安装器、IDE、备份工具等程序在后续访问时出现权限异常或兼容性问题。
这个插件为这些目录提供一条可控的清理路径:读取 DSH 的实时工作区列表(不是全盘遍历),先只读扫描并列出命中目录与命中类型,确认后只修复沙箱残留,修完再复扫校验。每个工作区保留一条可替换的 ACL 回滚记录,支持回滚上一次修复,或把记录彻底删除。
它识别三类对象:
- Low 完整性标签(SACL Mandatory Label,
S-1-16-4096) - 非继承的显式
S-1-4-*沙箱授权 ACE Everyone:(DENY)(DC),仅在同一个目录已经命中 Low 或 S-1-4 时才处理
正常的 X2\<用户名>:(F) 等授权不会被修改;单独出现的 Everyone 拒绝项不算命中,也不会被碰。
插件在 DSH 侧边栏提供一个白色的工作区映射页面,同时附带可脱离 DSH 单独运行的 PowerShell 引擎。
功能
- 扫描单个 DSH 工作区,或一键扫描全部工作区。
- 修复前必须确认;未加
-Apply时只读,不修改任何 ACL。 - 校验修复结果,显示剩余的
Low与S-1-4数量。 - 每个工作区只保留一条回滚记录;下一次成功修复会替换旧记录。记录可以一直保留,也可以永久删除,删除后不留下任何文件或空文件夹。
- 工作区映射直接读取 DSH 的实时工作区列表;在 DSH 里删除工作区后,插件页面对应卡片会自动消失。
- 无第三方依赖:Windows PowerShell 5.1 / PowerShell 7 + 内联 C# P/Invoke +
icacls。
安装
从 dsh-market 安装
目录条目合并后,在 dsh-market 搜索 文件完整性检查,点安装即可。
从源码安装
克隆仓库后,把这个目录作为本地 DSH bundle 安装。使用 DSH 的
plugin_manager:
plugin_manager action=install_bundle target="<仓库路径>\dsh-file-integrity-check"
安装后刷新 DSH Web GUI,侧边栏会出现盾牌图标 文件完整性检查。如果 Host 半有更新,需要完全退出并重新打开 DSH,只刷新页面只会更新 Client 半。
使用
- 点侧边栏 文件完整性检查。
- 每个 DSH 工作区一张卡片,列表来自 DSH 实时工作区。
- 扫描 只读检查。
- 修复 弹确认;确认后先保存 ACL,再修改。
- 校验 复扫并显示剩余数量。
- 顶部 扫描全部工作区 一次处理当前所有工作区。
修复成功后,卡片显示 可回滚,详情中可 回滚到上次状态 或 删除记录。删除记录会二次确认,并递归删除记录目录及空的父目录。
回滚记录
%LOCALAPPDATA%\dsh-lowlabel-fix\rollback\<路径 SHA256 前16位>\
里面是 manifest.json、root.acl、root.sddl,只保存 ACL 元数据,不保存
文件内容。同一工作区再次成功修复会整体替换该目录。
没有命中项的扫描/修复不会产生备份,也不会产生回滚记录。
命令行
# 扫描一个工作区(含子树)
powershell -NoProfile -ExecutionPolicy Bypass -File .\scripts\DshWorkspaceAcl.ps1 `
-Action scan -Path "D:\project" -Deep
# 修复;默认 dry-run,必须 -Apply 才修改
powershell -NoProfile -ExecutionPolicy Bypass -File .\scripts\DshWorkspaceAcl.ps1 `
-Action fix -Path "D:\project" -Apply
# 校验
powershell -NoProfile -ExecutionPolicy Bypass -File .\scripts\DshWorkspaceAcl.ps1 `
-Action verify -Path "D:\project"
# 查看回滚记录
powershell -NoProfile -ExecutionPolicy Bypass -File .\scripts\DshWorkspaceAcl.ps1 `
-Action records
# 回滚某个工作区
powershell -NoProfile -ExecutionPolicy Bypass -File .\scripts\DshWorkspaceAcl.ps1 `
-Action rollback -Path "D:\project"
# 永久删除某个工作区的回滚记录
powershell -NoProfile -ExecutionPolicy Bypass -File .\scripts\DshWorkspaceAcl.ps1 `
-Action delete-record -Path "D:\project"
-Json 只把 JSON 写到 stdout;进度和阶段信息走 stderr。
安全边界
- 只删除非继承的
S-1-4-*授权 ACE。 - 只在同一目录已命中 Low 或 S-1-4 时,才删除
Everyone:(DENY)(DC)。 - 只把 Low 恢复为 Medium。
- 不跟随 junction / reparse point。
- 修改前保存 ACL,失败项逐条列出,不中断整批。
- 不要求管理员权限;受保护的系统目录如果无权限,只报告并跳过,不强行修改。
环境要求
- Windows 10 / Windows 11
- DSH 0.2.1 或更新版本
- Windows PowerShell 5.1 或 PowerShell 7
目录结构
index.js Host 半:HTTP 路由 + PowerShell 调用
client.js Client 半:侧边栏入口 + 工作区页面
cordis.patch.yml DSH bundle patch
scripts/DshWorkspaceAcl.ps1 独立扫描/修复/校验/回滚引擎
locale/ 界面文案
marketplace/ dsh-market 目录条目与提交说明
开发说明
scripts/DshWorkspaceAcl.ps1 必须保存为 UTF-8 with BOM;Windows
PowerShell 5.1 没有 BOM 时可能把中文读成乱码并解析失败。没有构建步骤,也不
需要 node_modules。
许可
MIT,见 LICENSE。
No comments yet. Be the first to write one.