Isolated-environment browser verification skill for DSH plugin development: a throwaway DSH_HOME, its own `verify_<random>` profile, its own port and its own browser instance in one command, cleaned up on exit, so the profile you are actually using is never touched; ships a zero-dependency raw-CDP driver (snapshot / click / screenshot / eval) and an optional isolation audit.
Install
# from npm (prebuilt)
dsh plugin --profile web add @wingsky-1/dsh-verify-isolated
# from GitHub (first run asks for allowBuilds approval — follow the hint, retry)
dsh plugin --profile web add github:wingsky-1/dsh-plugin-hub#path:/packages/dsh-verify-isolated
Any plugin you install runs third-party code with your own permissions — it can read your files, use your credentials, and reach the network, and tool approvals don’t sandbox it. GitHub-sourced plugins also run build scripts at install time — pnpm blocks those until you allow them, so an install can stop with ERR_PNPM_GIT_DEP_PREPARE_NOT_ALLOWED or ERR_PNPM_IGNORED_BUILDS; dsh prints the exact key to add under allowBuilds in your profile’s pnpm-workspace.yaml, and the install works on the next run. Allowing a build is a trust decision: only install sources you trust, and pin a commit (github:owner/repo#sha).
README
An isolated-environment browser verification skill plugin for DSH plugin development:
quadruple isolation — temp DSH_HOME + dedicated verify_<random> profile + dedicated
port + dedicated browser instance — one command spins up an isolated dsh web, and it
cleans up on exit without polluting the web profile you are actually using.
Installation
dsh plugin --profile web add @wingsky-1/dsh-verify-isolated
After install / uninstall / update, restart
dsh webonce (bundle layers are only composed at startup) for changes to take effect.
After installation, the dsh-verify-isolated skill is automatically registered as a
built-in skill and becomes available to all sessions in the profile (check with
/skill dsh-verify-isolated).
How it works
- Built-in skill registration:
cordis.patch.ymlreuses the official@deepseek-ai/dsh-skill-filesystembundledSkillDirconfiguration and resolves this package'sskills/directory from the package manifest (following the archify-dsh pattern) — the official provider discovers and registersskills/dsh-verify-isolated/SKILL.md; no hand-written registration code needed; - Main line plus branches:
SKILL.mdcarries only what every run needs (when to use, quick path, the two hard preconditions, isolation self-check, verification and the done checklist); branch material (script contracts, manual setup, kernel troubleshooting, viewport-geometry methodology) lives inreferences/, each file self-contained and pointed at by the main line with the condition for reading it — a routine verification never loads the branches; - Quadruple isolation:
DSH_HOME=$(mktemp -d)isolates credentials/sessions/home-level patches; a dedicatedverify_<8 random chars>profile isolates the plugin composition stack; a dedicated port isolates the network surface; a dedicated browser instance (--browser) isolates pages/tabs/console — parallel sessions cannot see each other, structurally eliminating the tab-drift crosstalk of a shared MCP browser; - Self-contained browser driver
skills/dsh-verify-isolated/scripts/browser-driver.mjs: raw CDP, zero dependencies (only Node ≥22's built-in global WebSocket), launches an independent chromium (temp user-data-dir + a free debug port of its choosing + headless), atomic-operation CLI (snapshot / click / eval / fill / wait / screenshot / console / quit), uniform--jsonoutput, instance info written tobrowser.state; device emulation: page commands accept--width / --height / --dpr / --mobileto verify responsive layouts viewport by viewport — applied within the command and cleared before it exits, so commands never affect each other (why it is not sticky state, seescripts/lib/emulation.mjs: CDP's Emulation state is per session, so clearing across connections silently fails and leaks the size); a three-platform kernel detection chain (DSH_VERIFY_CHROMEenv → ms-playwright cache → PATH → common platform paths), fail-fast with install guidance when all are missing; - Minimal startup dependencies: profile bundles contain
@deepseek-ai/dsh-base+@deepseek-ai/dsh-web-app(built-in bundles are resolved by name from the dsh install directory, not via npm); - One-shot script
skills/dsh-verify-isolated/scripts/verify-isolated.mjs(Node implementation, requires Node ≥22): validate the dsh entry on PATH and require version0.2.1-rc.2→ create temp DSH_HOME → preset the first-run popup skip (writes the internal-testing notice version into the isolatedsettings.yaml, see below) → create profile (explicitplugin listinit) → inject web-app bundle → normalize plugin args (relative paths → absolute against cwd; package specs like@scope/name/ git URLs pass through) → build and link local plugins (--no-buildvalidates artifact presence + staleness warning) → (optionally--browser) launch a dedicated browser instance → start (explicit--host 127.0.0.1loopback +DSH_TELEMETRY_DISABLED=1telemetry off) → readiness probe → parse and print the token-bearing access URL (also written tobrowser.state.dshWebUrl) → unified cleanup on exit (dsh process + browser process + user-data-dir + DSH_HOME, no leftovers);--port 0auto-detects the real free port (no longer prints an invalid 0); B6 writes a startup-self-check verdict at$DSH_HOME/verdict.jsonafter ready (mode 0o600, three-channel port source, cleanup field finalized on exit); B7--evidence-dirdefaults to$DSH_HOME/evidence/, externalized as<dir>/evidence-<profile>/without ever touching the external directory; B4 optional isolated audit--audit— diffs the isolated$ISOLATED_HOMEwrite surface against a preset whitelist (versionedWHITELIST_V, pure functions inscripts/lib/audit.mjs); additions/deletions/modifications outside the whitelist plus escaping symlinks are reported as "suspicious" and do not block exit (--audit-extra-dirs <dir>adds extra audited dirs, must be a directory; limitation: real home is never scanned; the whitelist covers dsh's own write surface (.credentials.yaml/settings.yaml/settings.yaml.imported(pending real-device confirmation) /storages/**) while the officialprofiles/node_modules/**bundle links are captured by the post-readiness t0 baseline — the audit surface is the incremental write surface of the runtime;--keepwrites$DSH_HOME/audit/audit.json, otherwise the result is carried in the final verdict'sauditfield, and error-path JSON always carries anauditfield aligned with the verdict);--jsonemits only the final verdict JSON on stdout. Exit-code contract: 0 OK / 1 startup-or-readiness failure / 2 argument error / 130 SIGINT / 143 SIGTERM. - Optional real-host provider-usage probe (
--probe-provider-usage, not an offline CI gate): once the isolated instance is ready, request/api/dsh-provider-usage/stats?provider=deepseek-officialand/api/dsh-provider-usage/health, parse the whitelisted stats fields (ok/error/lastSuccessAt) and health fields (errors/fetchErrors), print a redacted report and exit immediately. If the isolatedDSH_HOME/.credentials.yamlhas norefsentry (arecords-only browser-session file does not count), the probe skips with "未验证(无凭据)" (unverified: no credentials) and exits 0; with a stored credential andok:trueor anerrorother thanno-api-keyit exits 0; with a stored credential butno-api-keyit exits 1 with actionable diagnostics. The probe never reads or copies real~/.dshcredentials, never treats inherited env keys as credential evidence (the V1 fallback would make it pass falsely), strips URL tokens, and echoes no secrets. Pure functions and the fetch-injectable thin I/O live inscripts/lib/provider-usage-probe.mjs. - First-run popups are skipped by default: a brand-new DSH_HOME opens on two
blocking dialogs ("Internal Testing Notice" → "Add an API key to get
started"); both set
#roottoinert, so every click on the page silently fails. Before startup the script reads both the namespace and the value from the target dsh client artifact at run time. It presets<namespace>.welcomeNoticeVersioninsettings.yamlonly when both facts are present; a missing fact means no preset and the browser-driver overlay probe handles the dialog after navigation to remove the first one; the API-key dialog cannot be preset away (its "Configure later" only holds for the current page lifetime and reappears on every reload), so browser-driver clicks through it after navigation. When no skip button is recognized it does not guess (the dialog may also offer a side-effecting "Save and continue"), reportingonboardingBlockedwith a warning instead.--no-skip-onboardingkeeps the native first-run state for verifying onboarding itself, and--no-auto-dismissmakes the browser side probe without clicking. The pure functions and probe live inscripts/lib/onboarding.mjs. - Access authentication (the token is mandatory): the dsh web GUI is
authenticated, and a bare port returns a 401 text page
(
dsh web authentication required); since the readiness probe treats any 2xx-4xx as ready, a missing token lets verification keep running against that 401 page. The token exists only in the line dsh prints at startup; the script parses it, prints it, and writes it tobrowser.state.dshWebUrl(0o600) for browser-driver's reserved--url statevalue; the verdict records only the token-freeweb.url, and every echoed URL is redacted (token=***), so the token never reaches CI logs or evidence files.
Package layout
skills/dsh-verify-isolated/
SKILL.md # skill definition (frontmatter name=dsh-verify-isolated; main line: when to use / quick path / hard preconditions / self-check / verification / done checklist)
references/script-contracts.md # branch: verdict fields, isolated-audit whitelist and timing, exit codes, Windows promise
references/manual-setup.md # branch: manual isolated-environment setup (the script's steps, expanded)
references/browser-kernel.md # branch: Chromium kernel detection chain, per-platform self-check and install
references/viewport-geometry.md # branch: per-viewport device emulation and geometry-assertion methodology
scripts/verify-isolated.mjs # one-shot isolated verification script (Node, requires dsh 0.2.1-rc.2 on PATH / --browser / --port 0 / --keep / --no-build / --evidence-dir / --audit / --audit-extra-dirs / --no-skip-onboarding / --json)
scripts/lib/verify-core.mjs # shared base utilities (exit-code constants/poll/findFreePort/port and token-URL parsing/C11 normalization)
scripts/lib/audit.mjs # B4 isolated-audit pure functions (scanSnapshot/diffAgainstWhitelist/checkSymlinkEscape/runAudit + versioned whitelist WHITELIST_V)
scripts/lib/emulation.mjs # device-emulation pure functions (parseEmulationFlags / buildDeviceMetrics; CDP session semantics)
scripts/lib/onboarding.mjs # first-run popup skip pure functions (version and namespace constant lookup / settings doc / overlay probe expression / token redaction)
scripts/lib/provider-usage-probe.mjs # optional real-host provider-usage probe (credential evidence / stats-health parsing / verdict / redacted report)
scripts/browser-driver.mjs # self-contained browser driver (raw CDP, zero deps, --json atomic CLI)
cordis.patch.yml # reuses official dsh-skill-filesystem + bundledSkillDir
lib/index.js # host gate export (name + empty apply)
Usage
Once the skill is loaded, follow its checklist; you can also call the package's one-shot
script directly. The script's resource base directory relative to the skill (the
Base directory for this skill: absolute path injected when the skill loads) is always
scripts/verify-isolated.mjs (Node implementation, requires Node ≥22). It adapts to the
install shape (npm copy / link: dev mode / in-repo browsing); see SKILL.md §2.
This package supports only dsh 0.2.1-rc.2 and is incompatible with every other runtime.
The dsh entry is resolved from PATH; a missing, unreadable, or mismatched runtime fails closed.
# Requirement: `dsh --version` on PATH is `0.2.1-rc.2`
node "$SKILL_BASE/scripts/verify-isolated.mjs" --port 3456 <plugin-package-path>
# parallel sessions / browser verification: --port 0 auto-detects the port,
# --browser launches a dedicated browser instance
node "$SKILL_BASE/scripts/verify-isolated.mjs" --port 0 --browser <plugin-package-path>
# externalize the evidence dir + emit only the final verdict JSON on stdout (human text on stderr)
node "$SKILL_BASE/scripts/verify-isolated.mjs" --port 0 --evidence-dir /tmp/my-evidence --json <plugin-package-path>
# isolated audit (B4): changes outside the whitelist are reported as suspicious and do not block exit;
# --keep writes $DSH_HOME/audit/audit.json
node "$SKILL_BASE/scripts/verify-isolated.mjs" --port 0 --audit --keep <plugin-package-path>
# optional real-host provider-usage probe: requests stats/health after readiness and exits;
# no credentials -> skip (exit 0); stored credential + no-api-key -> exit 1.
# Not an offline CI gate (offline judging stays with the package fixture tests)
node "$SKILL_BASE/scripts/verify-isolated.mjs" --port 0 --probe-provider-usage <plugin-package-path>
# keep the native first-run state (to verify the onboarding popups themselves;
# the skip is preset by default, see SKILL.md §4.1)
node "$SKILL_BASE/scripts/verify-isolated.mjs" --port 0 --no-skip-onboarding <plugin-package-path>
Plugin arguments accept either local plugin paths (relative paths are resolved to absolute paths against the current cwd before mounting — dsh otherwise parses a non-absolute path as a git URL) or package specs (npm package names / git URLs pass through unchanged).
Browser instance operations (instance info in $DSH_HOME/browser.state; the command
contract is in browser-driver.mjs --help. Page-operation commands need Node ≥22 —
they rely on the built-in global WebSocket; older versions error at connect time and
prompt for an upgrade):
# --url state: use the token-bearing URL from state (the GUI is authenticated;
# a bare port only yields a 401 text page)
node "$SKILL_BASE/scripts/browser-driver.mjs" snapshot --state "$DSH_HOME/browser.state" --url state
node "$SKILL_BASE/scripts/browser-driver.mjs" click --state "$DSH_HOME/browser.state" --selector "button.start"
node "$SKILL_BASE/scripts/browser-driver.mjs" screenshot --state "$DSH_HOME/browser.state" --url state --path shot.png
# device emulation (available on every page command): verify responsive layouts
# viewport by viewport; applied within the command and cleared when it exits
node "$SKILL_BASE/scripts/browser-driver.mjs" screenshot --state "$DSH_HOME/browser.state" --url state --width 375 --height 667 --path phone.png
node "$SKILL_BASE/scripts/browser-driver.mjs" eval --state "$DSH_HOME/browser.state" --width 375 --height 667 --expression "innerWidth+'x'+innerHeight"
Navigating commands automatically skip the first-run popups after navigation (the output
records the clicked buttons under dismissed; when no skip button is recognized it
reports onboardingBlocked with a warning). --no-auto-dismiss probes without clicking
and --overlay-wait <ms> tunes the popup wait window (default 1500). eval / fill do
not navigate and therefore do not trigger this logic.
Security model
- The isolated environment carries no real credentials (the temp
DSH_HOMEhas no~/.dshdata); the first-run popup skip only writes the isolated$DSH_HOME/settings.yaml(0o600) and clicks the dialog's own "Configure later" button — it injects and copies no API key. The script inherits the launching environment ({...process.env}, unchanged semantics), so provider credential variables already present there take effect per dsh's official precedence; launch from a shell without them if you need a fully clean credential surface; - Minimal token exposure: the token-bearing GUI URL is written only to the 0o600
$DSH_HOME/browser.state(dshWebUrl) and$DSH_HOME/dsh.log; every URL echoed by the script and browser-driver is redacted (token=***), and the verdict records only the token-freeweb.url— the token never reaches--jsonoutput, CI logs, or evidence archives; - The isolated
dsh webbinds explicitly to loopback (--host 127.0.0.1, reachable from this machine only) and explicitly disables telemetry (DSH_TELEMETRY_DISABLED=1, no test data leaves the machine); - Credential boundary of the provider-usage probe: it reads only the isolated
$DSH_HOME/.credentials.yamlto check whetherrefshas an entry (no value is parsed, stored, or echoed), and never reads or copies the real~/.dsh; inherited environment variables are not treated as credential evidence (an env key would make the probe pass falsely through the V1 fallback); stats/health output only whitelisted fields, URLs drop query/token, and error text goes throughredactSecrets; the probe never appends the access token. skip means "unverified", not "passed"; - Isolated verification covers the loopback access shape only (the script pins
--host 127.0.0.1). To verify LAN/mobile access, start it yourself with the official--trusted-host <authority>and confirm the plugin under test authenticates as expected in that shape; - It never stops/restarts the running main
dsh webprocess (dedicated port); - The browser instance binds only to a loopback debug port
(
--remote-debugging-address=127.0.0.1), reachable from this machine only; - The scripts only use
mktemp -dtemp directories, cleaned up on exit (with--browserthe browser process and user-data-dir are also cleaned up), leaving no leftovers.
Links
More in this category
zhu1090093659/dsh-web#packages/dsh-skill-explorer★ 9521
Skill center for the dsh web GUI: browse all loaded skills grouped by source, enable or disable model invocation, create new skills, and delete into a recoverable trash.
iflytek/skillhub#dsh★ 5292
Browse and search a SkillHub registry and manage local skill installation, updates, and removal inside DeepSeek Harness. Targets DSH 0.2.0-rc.2 and 0.2.1-rc.2; not yet compatible with 0.2.1-rc.3.
QingYunA/answer-me-with-html★ 4448
Answers a question with a one-page visual HTML explainer: the model writes a short Markdown draft and the bundled `am` CLI builds the page, with flow, sequence, tree, timeline and ER diagrams, tables and callouts.
hyhmrright/brooks-lint★ 1544
Provides six code quality skills for code review, architecture audits, technical debt, test quality, health dashboards, and remediation.
GanyuanRan/Aegis★ 1386
Software-engineering method pack for coding agents, with skills for baseline-first planning, systematic debugging, prompt hygiene, verification before completion, and repair/retirement tracking.
superdesigndev/superdesign-skill★ 904
Design skill for UI and marketing graphics on the Superdesign canvas: reads the repo for context, extracts its design system, then generates and iterates branchable design drafts, flow pages, and reusable components through the Superdesign CLI.
Community comments
Comments are public GitHub Discussions. Loading them connects to GitHub and Giscus; a GitHub account is required to post.