Introduction

When doing daily development with DSH Web, there are two types of errors that are relatively easy to encounter. One type occurs after the session permission has been switched to danger-full-access, but the model retry still carries the sandbox_permissions and justification fields. DSH rejects the request before actual execution, reporting not strictly wider. The other type appears in WSL environments: clicking on a file path in DSH Web reports spawn powershell.exe ENOENT, and the file cannot be opened.

DSH’s philosophy is that everything is a plugin, and such compatibility fixes are suitable to be implemented as out-of-tree plugins. Below, I introduce @MarvekG/dsh-plugins maintained by MarvekG, which provides a separate entry point for each of these two problems.

What is this

@MarvekG/dsh-plugins is a collection of out-of-tree DSH plugins, positioned as compatibility fixes and enhancements. Open source under the MIT license, current version 0.1.0, runtime dependency highlight.js ^11.12.0.

Currently, there are two entries within the package:

@MarvekG/dsh-plugins/sandbox-same-mode
@MarvekG/dsh-plugins/path-viewer

Entries are mounted individually via cordis.patch.yml, each having its own Cordis lifecycle, allowing for individual loading and unloading. For future new fixes, you only need to add a script, an exports subpath, and a separate patch line.

Also, pay attention to the package name: this package was renamed from @MarvekG/dsh-bug-fix. If you have installed the old package, upgrading cannot follow the “update” process; see the Installation section below for details.

Core Features

sandbox-same-mode: Handling redundant sandbox escalation fields

First, let’s look at the error itself. After the session permission has been switched to danger-full-access, the model retry may still carry such parameters:

{
  "file_path": "/home/wang/codes/StickyProxy/plugin/internal/state/store.go",
  "content": "x",
  "sandbox_permissions": "workspace-write",
  "justification": "write the requested plugin fix outside the workspace"
}

DSH reports an error before the write is actually executed:

sandbox escalation to "workspace-write" is not strictly wider than this call's current "danger-full-access" mode

The reason lies in the fact that effective permissions are determined by the session, while the tool schema exposes all possible escalation targets. The model may receive retry guidance under narrower permissions, and then after the session switches to the same or wider permissions, it continues to use those parameters. In the example, workspace-write is narrower than the current danger-full-access, and the request fields do not increase capability, so DSH correctly rejects it as a non-escalation request.

The plugin’s approach is to wrap the execution function during tool registration, thereby covering both regular global tools and DSH Web’s preset-scoped bash, pwsh, write, and edit tools. It only removes the escalation fields and executes based on current permissions if the following conditions are met simultaneously:

  1. sandbox_permissions is an enum value explicitly exposed by the tool schema;
  2. justification is a non-empty string;
  3. The requested permission is not wider than the current call or the current session’s effective sandbox permissions.

At this point, the request is just a redundant declaration; no approval prompt appears, and the not strictly wider error is no longer reported.

True permission escalation and illegal input still follow the original process:

  • read-only → higher permissions: continue to request approval;
  • workspace-writedanger-full-access: continue to request approval;
  • Missing justification, empty justification, or incomplete parameters: continue to report errors;
  • Permission values not exposed by the tool schema (including forged equivalent values): are still rejected by DSH’s original parameter validation.

This entry does not expand the workspace, does not modify workspaceRoot, and does not secretly increase permissions. When effective permissions remain workspace-write, after removing redundant escalation fields, requests outside the workspace may still be rejected due to sandbox workspace boundaries.

path-viewer: Viewing files and directories in the browser

The second type of error occurs when clicking on a file path in DSH Web under WSL:

path open failed: path open failed: spawn powershell.exe ENOENT

Under WSL, DSH passes the path to Windows Desktop via powershell.exe. If /etc/wsl.conf is configured with [interop] appendWindowsPath = false, the Windows directory is not appended to PATH, causing the bare command name to spawn directly with ENOENT. Moreover, “launching Windows Desktop from WSL” is inherently fragile—the GUI itself runs inside a Windows browser.

The plugin replaces the native opening with a pure browser solution, without spawning any Windows processes throughout. Specifically, it consists of two steps:

  1. Register a GET /view?path=<absolute path>[&line=N] on the same web service with a loopback fence: files are rendered as line-numbered tables (HTML escaped, tab=4, truncation banner for over 4 MiB, binary files not rendered), and directories are rendered as clickable list pages.
  2. Inject a head script into the GUI page via webserver/index-inject: intercept RPCs sent to /api/host.openPath and /api/host.openTextFile, change them to use window.open('/view?path=…') to display in a new tab, and forge a successful response in the shape of an online packet ({type:'server-response',rpcId,result:{ok:true,value:{opened:true}}}); if the new tab is blocked by the browser, the original request is automatically allowed to pass.

Common source code is syntax highlighted by highlight.js, and unknown extensions are safely displayed as plain text. This entry provides two configuration options:

  • maxBytes: maximum bytes for a single render;
  • intercept: list of RPC methods to reroute.

Installation and Enablement

You need to install it first and confirm that dsh runs normally. Default installation from GitHub:

dsh plugin --profile web add github:MarvekG/dsh-plugins
dsh web

Here, web is the DSH profile name; if you are using another profile, replace web with the corresponding name. Restart DSH Web after installation for it to take effect.

If you don’t want to follow the latest code in the repository, you can fix the version by adding a commit SHA after the repository address:

github:MarvekG/dsh-plugins#<sha>

Upgrading from the old package name

The package has been renamed from @MarvekG/dsh-bug-fix to @MarvekG/dsh-plugins. Since the package name has changed, the “update” process cannot be used for a smooth switch, and old entries will remain in the profile. Uninstall first, then install:

dsh plugin --profile web remove @MarvekG/dsh-bug-fix
dsh plugin --profile web add github:MarvekG/dsh-plugins
dsh web

Do not restart DSH Web between uninstallation and reinstallation to avoid assembly warnings caused by the missing old name.

Typical Usage

Local Debugging

After cloning the repository, execute the following in the repository root directory:

dsh plugin --profile web add .
dsh web

Manually viewing paths

After the path-viewer takes effect, in addition to paths being rerouted when clicked in DSH Web, you can also access them directly:

GET /view?path=<absolute path>[&line=N]

Files are rendered as line-numbered tables, directories as list pages, and the line parameter is used to locate the line number.

Uninstallation and Updates

Remove the plugin from the profile:

dsh plugin --profile web remove @MarvekG/dsh-plugins

When updating, remove the old version first, then install the new version:

dsh plugin --profile web remove @MarvekG/dsh-plugins
dsh plugin --profile web add github:MarvekG/dsh-plugins
dsh web

For local debugging, replace the second command with:

dsh plugin --profile web add .

Running Tests

Execute the following in the plugin directory:

npm test

Applicable Scenarios and Notes

Two types of scenarios are suitable for installing this plugin: one is repeatedly encountering not strictly wider errors and hoping redundant escalation fields won’t interrupt the session; the other is using DSH Web in a WSL environment where clicking paths reports spawn powershell.exe ENOENT. If you haven’t encountered either of these problems, there is no need to install it for now.

Confirm the following points before use:

  1. DSH Web must be restarted for installation or updates to take effect; the plugin will not retroactively wrap existing session tool definitions before the restart.
  2. The plugin does not expand the workspace, does not modify workspaceRoot, and does not secretly increase permissions. When effective permissions are workspace-write, requests outside the workspace may still be rejected due to sandbox boundaries.
  3. The plugin runs with the current dsh process permissions; you should check the source code and license before installation. The project uses the MIT license, and the source code can be reviewed directly on GitHub.

Conclusion

@MarvekG/dsh-plugins handles two types of practical compatibility issues with two independent entries: redundant sandbox escalation fields execute according to current permissions when conditions are met, interrupting the session no longer; path viewing is changed to a pure browser solution, no longer relying on launching Windows processes from WSL. It also demonstrates DSH’s “everything is a plugin” extensibility approach—each fix is an entry point that can be loaded and unloaded independently.

  • Project address: https://github.com/MarvekG/dsh-bug-fix
  • Community plugin directory: https://www.skillhub.cn/plugins/MarvekG/dsh-bug-fix