runseal-labs
dsh-tool-runseal
RunSeal 沙箱插件:为 dsh 提供 OS 原生策略执行边界(Windows/macOS/Linux) | RunSeal sandbox provider for DeepSeek Harness — OS-native policy-enforced command execution
- Stars
- 0
- Language
- TypeScript
- Created
- Aug 15, 2026
- Updated
- Aug 15, 2026
Introduction
dsh-tool-runseal
English | 中文
A standalone DeepSeek Harness plugin: replaces the built-in sandbox with RunSeal — an OS-native, policy-governed execution environment with enforceable filesystem, process, resource, and network boundaries, plus structured audit events and environment-credential scrubbing.
Fully out-of-tree: depends only on published dsh base packages. Registers as ctx.sandbox, so every existing sandbox consumer (bash, jobs, fs) confines through RunSeal automatically.
What it provides
| Item | Description |
|---|---|
ctx.sandbox provider | Subclasses SandboxProvider; confine() wraps argv through a thin Node wrapper that runs the command under runseal rpc |
| Policy mapping | dsh read-only / workspace-write / danger-full-access → same-named RunSeal sandbox levels |
| Network modes | unmanaged (default), disabled, proxy (enterprise routing + credential redaction) |
| Streaming output | execution.stdout / execution.stderr RPC events forwarded to the consumer's stdio; exit code propagates |
| Fail closed | Missing setup or an unavailable backend rejects with runseal: <reason> on stderr and a non-zero exit, never silent passthrough |
| Audit | Every execution emits execution.requested → policy.resolved → execution.finished events and a JSONL audit record |
Install
Prerequisites: a runseal binary on PATH (or an absolute command path). Prebuilt binaries for Windows / macOS / Linux are published on the runseal releases page.
On Windows, confined modes (read-only, workspace-write) require the sandbox setup once:
runseal setup windows-sandbox --cwd <workspace> --elevate
Then install the plugin into your dsh profile:
cd ~/.dsh/profiles/web && pnpm add dsh-tool-runseal
# or from source:
# git clone https://github.com/runseal-labs/dsh-tool-runseal && cd dsh-tool-runseal && pnpm install && pnpm build
Mount into dsh
RunSeal takes over ctx.sandbox. Patch the base bundle's sandbox-local row out and insert this plugin:
# cordis.patch.yml — replace the built-in local sandbox with RunSeal
- id: sandbox-local
disabled: true
- insert:
- id: sandbox-runseal
name: 'dsh-tool-runseal'
inject: [sandbox]
config:
# runseal executable: absolute path, or a name resolved on PATH
command: 'runseal'
# network mode: unmanaged (default), disabled, or proxy
networkMode: 'unmanaged'
# default per-execution timeout in ms
timeoutMs: 600000
Note:
ctx.sandboxis a single-service key. The base bundle'ssandbox-localrow must be disabled (or replaced) so the RunSeal provider registers instead. Keep a backup of your patch before switching.
Configuration
| Field | Default | Meaning |
|---|---|---|
command | — (required) | The runseal executable: absolute path or PATH-resolved name. |
args | [] | Extra arguments before the rpc subcommand (no shell). |
networkMode | unmanaged | Network policy: unmanaged, disabled, or proxy. |
maxStdinBytes | 65536 | Maximum stdin bytes for the bytes mode (runseal cap). |
timeoutMs | 600000 | Default per-execution timeout in ms. |
autoSetup | true | On Windows, automatically run runseal setup windows-sandbox --elevate for the workspace when a confined execution fails because setup is missing, then retry once. The elevation prompts the user through UAC once. |
How it works
confine() is synchronous by contract, so it returns a wrapper argv immediately:
[node, wrapper.cjs, {"argv": [...], "cwd": ..., "policy": ..., "network": ..., "timeoutMs": ...}]
When the consumer spawns it, the wrapper starts runseal rpc --stdio, sends one execute request, forwards the execution.stdout / execution.stderr event payloads to its own stdio, and exits with the command's exit code. Consumers see an ordinary subprocess lifecycle — no dsh core changes needed.
Known Limitations and Deferred Work
- stdin is not streamed — RunSeal's
executeacceptsstdin: { mode: 'bytes' | 'file' }, not an interactive stream. The wrapper drains consumer stdin; long-lived interactive commands (REPLs) are not supported yet. - Windows confined-mode setup is automatic — with
autoSetup(default on), the first confined execution in a workspace triggersrunseal setup windows-sandbox --elevate(one UAC prompt) and retries; no manual setup command needed. Turn it off if you prefer to run setup yourself. - Single provider at a time —
ctx.sandboxaccepts one provider; switching fromsandbox-localrequires disabling its row (the patch above does this). - No fallback chain — unlike
sandbox-local(bwrap→Landlock→Seatbelt→ACL), this provider does not chain to other runners; runseal must be usable or the call fails closed.
Development
pnpm typecheck # tsc --noEmit
pnpm test # vitest (protocol + confine unit tests)
pnpm lint # oxlint
pnpm build # tsc + copies wrapper.cjs into lib/
License
MIT