
Product
Socket Threat Intel Now Shows Which Malware Campaigns Were Blocked or Detected
Socket Threat Intel now shows which malware campaigns were blocked or detected in your organization, with links to scans and Firewall events.
dsh-win-multi-bash
Advanced tools
Windows multi-bash plugin for dsh: git_bash / wsl_bash model tools, each owning its own Git Bash / WSL executor and leaving the ctx.shell seat to dsh's own pwsh executor.
English | 中文
A Windows multi-bash plugin for DeepSeek Harness: the git_bash / wsl_bash model tools, each owning its own Git Bash / WSL executor. The plugin never touches the ctx.shell seat — dsh's own pwsh executor keeps it — so pwsh behavior is identical to a deployment without the plugin.
| Tool | Backend | Dialect | Notes |
|---|---|---|---|
git_bash | git-bash | MSYS | Owns a GitBashExecutor; Git for Windows toolchain |
wsl_bash | wsl-bash | Linux | Owns a WslBashExecutor; WSL distro Linux userland |
pwsh (dsh's own) | pwsh | — | Served by the base bundle's pwsh-sandbox row, untouched by this plugin |
ctx.shell, so the seat — and every plugin that injects shell (dsh's tool-pwsh, permission-presets, …) — is unaffected by this plugin being loaded.ShellExecRequest.shell, the routing field the pre-0.1.7 shell-select design dispatched on. With no routing input left, the tool is what knows which shell it wants — so the selector has nothing to select on, and is gone.gitBash.bashPath, Git install roots inferred from git.exe layout directories on PATH (so an install reachable through git is found without a pin, even outside the well-known locations), the well-known Program Files layout on every fixed drive (C:\Program Files\Git, D:\Program Files\Git, ...), bash.exe on PATH, and finally the HKLM\SOFTWARE\GitForWindows install path (which the Git for Windows installer always records, covering portable installs). The Windows WSL launcher System32\bash.exe and WindowsApps app-execution alias directories are never selected, and candidates must be real regular files — symlinks/reparse points are rejected — so a stale WSL bash.exe alias can never shadow a real Git Bash (this tool is MSYS, not WSL).auto: Git Bash probes the windows-acl runner, WSL probes bwrap inside the distro; a failed probe degrades honestly to an unconfined run with no sandbox facts. An explicit sandbox: bwrap with bubblewrap missing fails loudly at the first wsl_bash command (never at boot), leaving the other backends untouched.The three backends do not share the same file-sandbox capability:
| Backend | Mechanism | enforcement | On probe failure |
|---|---|---|---|
pwsh | windows-acl restricted-token runner | partial | no probe — always confined (dsh's own executor) |
wsl_bash | bwrap (bubblewrap) inside the distro | full | runs unconfined, no sandbox facts |
git_bash | windows-acl runner wrapping MSYS bash | partial (when the probe passes) | runs unconfined, no sandbox facts when the probe fails |
⚠️
git_bashusually cannot be sandboxed in Git for Windows deployments. The windows-acl runner fails to launch the MSYSbash.exeunder a restricted token (CreateProcessAsUserWreturns Win32 error 2;cmd.exeandpwsh.exelaunch fine). Withsandbox: auto, a failed probe degrades to an unconfined run by contract. Do not assumegit_bashis protected by the DSH sandbox — for sensitive operations usepwsh(restricted token active) orwsl_bash(bwrap active), or take the explicit escalation-approval path.⚠️
wsl_bashsandboxing depends on bubblewrap inside the distro. Without bwrap,autodegrades to unconfined as well; the probe verdict is cached for the host process lifetime — after installing bwrap you must restartdsh web(or reload the tool row by editing the profile patch) before it is re-probed.⚠️ A denial is only classified when the command exits non-zero. If a blocked write is followed by a successful command (
echo nope > /etc/x; echo done), the overall exit is 0 and no[sandbox: file access denied]marker is emitted — matching the upstream bash-sandbox rule to avoid false positives.The sandbox constrains file effects only (
workspace-write/read-only); network and other resources are not limited.requireSandbox: refuse unconfined runs when the probe fails (optional hardening). Both backends supportrequireSandbox: true(defaultfalse, keeping the existing degrade-and-run behavior). When enabled, a failed probe (windows-acl unusable for git-bash / bwrap missing for wsl-bash) means:danger-full-accessruns as usual (an unconfined run is equivalent to an explicit full-access grant), whileread-only/workspace-writecalls are refused with an error naming the fix and the escalation path. The tool layer also advertises the sandbox and opens thesandbox_permissionsargument, so the model can take the approval-based escalation. Example:
# the win-mb-tool-git / win-mb-tool-wsl rows in cordis.patch.yml:
# each tool row carries only its own backend's partition
- id: win-mb-tool-git
name: 'dsh-win-multi-bash/tool-git-bash'
config:
gitBash: { requireSandbox: true }
- id: win-mb-tool-wsl
name: 'dsh-win-multi-bash/tool-wsl-bash'
config:
wslBash: { requireSandbox: true }
requireSandboxandsandbox: noneare mutually exclusive in intent — explicitnoneis a deliberate opt-out and stays allowed;requireSandboxonly governs the "sandbox wanted but probe failed" case.
wsl_bashwsl_bash sandboxing requires bubblewrap inside the distro. On Ubuntu/Debian:
wsl.exe -d Ubuntu-24.04 -e sudo apt-get install -y bubblewrap # install straight from Windows
wsl.exe -d Ubuntu-24.04 -e bash -c "command -v bwrap && bwrap --version" # verify
wsl -l -q; if your target distro is not the first, pin it via wslBash.wslDistro in cordis.patch.yml and install bwrap inside that distro (e.g. Ubuntu-24.04; docker-desktop has no bash and cannot be used).sudo may require a password (depending on the distro's sudoers configuration); use apt-get install -y for scripting.dnf install bubblewrap, Alpine apk add bubblewrap.dsh web (or reload the tool row by editing the profile patch) — the probe verdict is cached for the host process lifetime, and wsl_bash stays unconfined until then.The git_bash / wsl_bash tool descriptions are deliberately concise and mirror the official tool-pwsh skeleton: a fresh shell per call, the dialect's paths/env form, [exit code: N] markers, $DSH_* environment facts, sandbox behavior, output truncation, delete/move target verification, the unset-variable ${VAR:?} guard, background jobs, and the escalation contract. The longer dialect notes (MSYS path rewriting, WSL base64 payloads) live in this README rather than in the model-facing text.
Both tools run bash -c, so that safety guidance is worded as in tool-bash, not as in tool-pwsh: $HOME is an ordinary assignable variable in bash, so pwsh's "do not assign to automatic variables" sentence would be wrong here — the bash guard for a computed path is the ${VAR:?} form above, which makes an unset variable fail instead of silently expanding to an empty string.
git_bash's description additionally carries a path-format hint:
MSYS paths work inside Git Bash only — dsh's file tools (
read,write,edit) on Windows take nativeC:\...paths.
So when a command prints an MSYS path (e.g. /d/WorkSpace/foo), convert it to its Windows form (D:\WorkSpace\foo) before handing it to dsh's file tools; inside the bash command itself, MSYS paths are what the shell expects.
workdir accepts native, MSYS and WSL-automount forms. A model told that the dialect's paths are MSYS- or WSL-shaped will naturally write workdir that way, so the resolver translates a single-letter drive form (/c/...) and the WSL automount form (/mnt/c/...) into the native C:\... before the executor hands the value to spawn; MSYS POSIX roots (/etc, /usr, /tmp) and distro-side paths such as /mnt/data are left untouched, and a relative workdir still resolves against the session workspace. Before that translation an MSYS-form workdir failed as spawn <shell> ENOENT — a missing-shell symptom for what is really an unusable cwd.
Each tool row also registers a short system-prompt section (tool:<name>): check the [exit code: N] marker on every result, and chain dependent steps with && or set -o pipefail — ; never stops on failure, and cmd | tail returns the status of tail, not of cmd. That is guidance about composing a multi-step command rather than about one call's arguments, so it belongs to the prompt instead of the per-call schema; it also makes the runtime's own tail truncation the reason not to bound output with a pipe.
Git Bash rewrites leading-slash POSIX paths into Windows paths (e.g. <Git root>\root) whenever a native Windows program is called — standard MSYS behavior, not a plugin defect. Calling wsl.exe (or any native exe) with POSIX paths from inside git_bash therefore fails:
wsl.exe -e ls /root # ✗ ls: cannot access 'D:/Program Files/Git/root'
MSYS_NO_PATHCONV=1 wsl.exe -e ls /root # ✓ passed verbatim
MSYS_NO_PATHCONV=1 (or MSYS2_ARG_CONV_EXCL="*"); a single argument can be escaped with a // prefix.wsl_bash tool: it spawns wsl.exe directly from Node and ships the command as a base64 payload, so quoting and Linux paths reach the distro verbatim — no rewriting involved.The full feature implementation ships in lib/ as plain ESM JS — no build step — and imports only dsh's published base packages:
lib/
├── bash-git/ GitBashExecutor (MSYS)
├── bash-wsl/ WslBashExecutor (WSL, base64 payloads)
├── tool-bash/ tool factory + git_bash / wsl_bash instances,
│ backend ownership (types/backend.js)
└── vendor/ helper modules for runner-failure classification and bwrap profiles
Because no row of this plugin registers as ctx.shell, the patch inserts only its own two tool rows and disables nothing: the base bundle's shell wiring (pwsh-sandbox on win32, bash-sandbox elsewhere) stays exactly as shipped, and pwsh keeps working whether or not this plugin is loaded.
@deepseek-ai base packages (every standard deployment).Two mutually exclusive paths insert the same rows. Never use both at once — the loader rejects duplicate entry ids.
# Install
powershell -ExecutionPolicy Bypass -File .\install.ps1 # default profile: web
powershell -ExecutionPolicy Bypass -File .\install.ps1 -ProfileName <name>
# Uninstall
powershell -ExecutionPolicy Bypass -File .\uninstall.ps1
The script links the package into <profile>/node_modules/ (a junction), maintains the package-local node_modules/@deepseek-ai junction the bundled code needs, and writes a managed block into the profile's cordis.patch.yml — dsh web hot-reloads that file, so the feature goes live without a restart. The script is idempotent and auto-detects Git Bash installs outside the default probe paths by reading HKLM:\SOFTWARE\GitForWindows and pinning gitBash.bashPath.
# Install (pick one)
dsh plugin --profile web add dsh-win-multi-bash # npm published package (recommended)
dsh plugin --profile web add github:@Dinosaur-MC/dsh-win-multi-bash # GitHub repository source
# Uninstall
dsh plugin --profile web remove dsh-win-multi-bash
Requires pnpm (dsh plugin is a pnpm forwarder); the bundle layer is assembled at boot, so restart dsh web for it to take effect. Works on any profile, including freshly initialized ones.
powershell -ExecutionPolicy Bypass -File .\smoke\run.ps1
Boots a real composition over the profile runtime (modifying nothing), verifies git_bash / wsl_bash register and execute real commands — including an explicit bashPath variant — and asserts ctx.shell is still provided by the base bundle's own row (the regression this plugin once caused). Requires node >= 20.
powershell -ExecutionPolicy Bypass -File .\smoke\audit.ps1
Runs the full audit suite instead: pure-unit coverage of the vendor helpers, executor internals and tool config schemas, plus boot-integration matrices for the real cordis.patch.yml and for misconfigurations.
| Symptom | Fix |
|---|---|
New sessions lack git_bash / wsl_bash | Check the managed block exists in the profile patch, the profile node_modules/dsh-win-multi-bash junction exists, and the package-local node_modules/@deepseek-ai junction exists (re-run install.ps1); confirm the running dsh web hot-reloads the profile patch |
Boot fails with duplicate loader entry id | Both plug paths are active; remove one of them |
Boot fails with Cannot find package '@deepseek-ai/...' | The package-local node_modules/@deepseek-ai junction is missing (re-run install.ps1), or the profile runtime lacks the base packages |
git_bash reports bash not found (or spawns the WSL WindowsApps\bash.exe alias with spawn ... ENOENT) | Git Bash is outside the probe paths, or a stale WSL app-execution alias shadows resolution: delete %LOCALAPPDATA%\Microsoft\WindowsApps\bash.exe (Settings → Apps → Advanced app settings → App execution aliases), re-run install.ps1 (registry auto-detect), or set gitBash.bashPath manually |
wsl_bash errors | Check wsl.exe --status for a default distro; set wslBash.wslDistro to name one |
wsl_bash fails with bwrap was not found | sandbox: bwrap is set but bubblewrap is missing inside the distro: install it per “Sandbox behavior → Enabling the bwrap sandbox for wsl_bash” (sudo apt-get install -y bubblewrap) and restart dsh web, or use sandbox: auto / none |
wsl_bash sandbox reports a runner failure on bwrap | The bwrap workspace root is the Linux side of a Windows drive path (/mnt/<drive>/...): a UNC workspace root fails loud, and a distro with a custom automount root (wsl.conf automount.root) needs a matching configuration |
Calling wsl.exe (or other native exes) with POSIX paths from git_bash reports No such file or directory | MSYS rewrote /root etc. to <Git root>\root: prefix with MSYS_NO_PATHCONV=1 / MSYS2_ARG_CONV_EXCL="*", or use a // prefix; use the wsl_bash tool for WSL work |
wsl_bash still runs without a sandbox after installing bubblewrap | The bwrap probe verdict is cached for the host process lifetime: restart dsh web, or reload the tool row by editing the profile patch |
Boot warns win-mb-tool-git … waiting for service: shell (or dsh's own tool-pwsh / permission-presets do) | Nothing provides ctx.shell. This plugin no longer provides it either: check the base bundle's pwsh-sandbox row is not disabled by some other patch |
dsh-win-multi-bash/
├── package.json # dsh.bundle manifest; exports ./tool-git-bash ./tool-wsl-bash
├── cordis.patch.yml # the composition wiring (documented inline)
├── install.ps1 # Path A hot plug (junctions + managed block + Git Bash detection)
├── uninstall.ps1 # Path A hot unplug
├── LICENSE / THIRD_PARTY_NOTICES
├── lib/ # bundled implementation (plain ESM JS, no build step)
└── smoke/ # smoke test (not published)
FAQs
Windows multi-bash plugin for dsh: git_bash, wsl_bash and opt-in msys2_bash model tools, an opt-in ssh_bash dialect that drives a remote shell over the OpenSSH client, and a terminal tool that keeps a persistent PTY session. Each dialect owns its own exec
The npm package dsh-win-multi-bash receives a total of 0 weekly downloads. As such, dsh-win-multi-bash popularity was classified as not popular.
We found that dsh-win-multi-bash demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.

Product
Socket Threat Intel now shows which malware campaigns were blocked or detected in your organization, with links to scans and Firewall events.

Security News
Fixes for eMudhra and Brotli are out. Getting them everywhere they’re needed means tracking down bundled libraries, runtimes, and certificate stores.

Threat Research
/Security News
Socket uncovered secret-stealing workflows that ran in LiteLLM’s GitHub repository 11 days before the supply chain attack on PyPI and Docker.