
Security News
vlt 1.5.0 Adds Agent Skills Management
vlt 1.5.0 links skills from JavaScript dependencies to coding agents, with lockfile versioning and Socket data to filter out known malicious packages.
dsh-reverse-proxy
Advanced tools
Authenticated provider-neutral reverse proxy and mobile control UI for DeepSeek Harness Web
English | 中文
An installable DeepSeek Harness bundle that creates an authenticated local reverse-proxy endpoint for the DeepSeek Harness Web UI, plus a sidebar control panel to run it. It is intentionally independent of Tailscale, frp, ngrok, cloudflared, WireGuard, SSH, or any other tunnel.
The plugin does not launch or manage tunnel software. Point your tunnel at the
local target shown in the DeepSeek Harness sidebar, for example http://127.0.0.1:3081.
Each feature is shown against a clean harness profile (no personal data).
| Feature | Screenshot |
|---|---|
| Sidebar entry — own row above the other footer actions | ![]() |
| Control panel — status, tunnel target, one-click copy | ![]() |
| Runtime publish address — non-loopback warning before applying | ![]() |
| Access token — reveal and rotate | ![]() |
| Remote login gate — desktop | ![]() |
| Remote login gate — mobile (390×844) | ![]() |
cordis.yml; the choice persists and survives restarts.
A running proxy restarts on the new address, and a failed bind rolls back
to the previous working address automatically.0600) with atomic writes; autoRestore re-enables the
proxy after a DeepSeek Harness restart.DeepSeek Harness normally trusts its loopback Web endpoint. A generic tunnel can be public,
so merely rewriting Host would expose that trusted API. This plugin places an
authentication gate before the proxy:
0600;set-cookie is stripped (the backend cannot establish cookies with remote
browsers anyway);Keep the token secret. Use HTTPS on the public side of your tunnel.
Several community plugins solve parts of remote access. They are listed in the awesome-dsh-plugin registry; the table below is based on that registry's descriptions and each project's own README.
| dsh-reverse-proxy (this) | dsh-web-lan-access | dsh-mobile-gate | |
|---|---|---|---|
| Model | Authenticated reverse proxy you point any tunnel at (frp/ngrok/cloudflared/SSH) | Direct LAN links: injects a crypto.randomUUID polyfill so the stock frontend survives plain-HTTP origins | Isolated child-process reverse proxy with a LAN mobile gateway |
| Authentication | 192-bit token → per-device HttpOnly session cookie (hash at rest) | None (trusts the LAN) | First-visit approval + per-device token binding |
| First-visit approval | Optional approval mode with polling wait page | — | Built-in first-visit approval |
| Device management | Panel lists devices, kick any one instantly | — | Per-device binding |
| Login throttling | Per-IP 429 lockout + fixed delay | — | Rate limiting |
| WebSocket / SSE | Full forwarding with session teardown | n/a | — |
| Control surface | Sidebar panel: start/stop, runtime listen address with rollback, token reveal/rotate | — | — |
| Runtime reconfiguration | Republish on a new IP/port from the UI, persisted | — | — |
Why pick this plugin:
Why pick one of the others:
This plugin also injects the crypto.randomUUID polyfill (guarded, only when
the browser lacks it), so remote file attachments keep working on plain HTTP.
The plugin needs the webServer service, which the official
@deepseek-ai/dsh-web-app bundle provides. Its npm dependencies are not yet
fully published, so a profile that does not already carry web-app must get it
from a harness source checkout first:
# Once, if your profile lacks the official web bundle:
dsh plugin --profile web add /path/to/deepseek-harness/packages/bundle/web-app
# 1. Build the package tarball (once, in this repo)
pnpm pack
# 2. Add this plugin to the profile (the profile is created on first use)
dsh plugin --profile web add ./dsh-reverse-proxy-0.1.0.tgz
# 3. Start DeepSeek Harness
dsh --profile web
After the package is published to npm, step 2 becomes a one-liner:
dsh plugin --profile web add dsh-reverse-proxy. Git installs
(dsh plugin add github:JUANWANG-BUAA/dsh-remote#<sha>) work through the
self-contained prepare script; pnpm ≥10 users must allow the build with
allowBuilds: { dsh-reverse-proxy: true } in the profile workspace.
Open http://127.0.0.1:3080. The 反向代理 action sits at the bottom of the
sidebar, directly above Settings. Start the endpoint, copy its local target,
and configure your tunnel:
# Examples only — the plugin does not run these commands.
cloudflared tunnel --url http://127.0.0.1:3081
ngrok http http://127.0.0.1:3081
ssh -R 8080:127.0.0.1:3081 user@example-host
The remote browser receives a token login page before any DeepSeek Harness content.
Open the sidebar panel and edit LISTEN ADDRESS: set the IP/host and port
(0 picks a free port), then press 应用发布地址. The override is written
to the state file, applied immediately (restarting a running proxy), and used
again after DeepSeek Harness restarts. If the new address cannot bind, the plugin rolls
back to the previous working address and reports it in the panel.
Binding a non-loopback address shows a warning in the panel: it exposes the port directly, so firewall rules must be explicit.
DeepSeek Harness composes Client plugins once per process, not once per browser viewport —
the same process cannot refuse to load a bundle (such as a desktop-only
@linxin666/dsh-web-ui-all) for phones while serving it to desktops. A CSS
media query only hides the bundle after loading and running it. The supported
way to give phones a lean UI is a second profile:
# Desktop: keep the full third-party UI on 127.0.0.1:3080.
dsh --profile web
# Mobile: official web bundle (its npm deps are still unpublished, so install
# it from a source checkout) + this plugin, served separately.
dsh plugin --profile mobile add /path/to/deepseek-harness/packages/bundle/web-app
dsh plugin --profile mobile add ./dsh-reverse-proxy-0.1.0.tgz
dsh --profile mobile --port 3082
Configure the tunnel to use the proxy target exposed by the mobile profile
(and set that profile's listen port in the panel if you need a fixed value).
Desktop browsers continue using the full web profile. This is true code-level
isolation: the desktop bundle is never part of the mobile process.
- id: reverse-proxy
name: dsh-reverse-proxy
config:
listenHost: 127.0.0.1
listenPort: 3081
backendHost: 127.0.0.1
backendPort: 0
autoRestore: true
maxRequestBytes: 16777216
upstreamTimeoutMs: 15000
sessionMaxAgeSeconds: 2592000
cookieName: dsh_reverse_proxy_session
maxHeaderSizeBytes: 16384
headersTimeoutMs: 15000
keepAliveTimeoutMs: 5000
loginDelayMs: 250
loginMaxAttempts: 5
loginLockoutSeconds: 300
approvalMode: false
maxSessions: 16
logRequests: false
stateFile: ""
listenHost / listenPort are defaults; the panel can override them at
runtime and the override persists.backendPort: 0 follows the active webServer.port.listenPort: 0 chooses a free port and displays it in the UI.stateFile: "" uses $DSH_HOME/reverse-proxy.json.maxHeaderSizeBytes, headersTimeoutMs, keepAliveTimeoutMs, and
loginDelayMs are server-hardening knobs; the defaults are safe and rarely
need changing.loginMaxAttempts / loginLockoutSeconds rate-limit failed logins per
remote IP: after loginMaxAttempts failures within the window the IP is
rejected with 429 (and Retry-After) until the lockout expires. Users
behind a shared NAT IP share one bucket — raise the limits if that hurts.approvalMode: true holds every new device on a waiting page until it is
approved from the panel (rejected devices never reach DeepSeek Harness).maxSessions caps concurrent devices; the stalest session is evicted past
the cap and sessions expire after sessionMaxAgeSeconds without activity.logRequests: true logs every proxied request at debug level; lifecycle
events (start, stop, token rotation, publish-address changes) are always
logged at info level.listenHost on loopback when the tunnel process runs locally. Binding a
LAN address is an explicit expansion of the attack surface.webServer, so it only works in Web-serving profiles
that include the @deepseek-ai/dsh-web-app bundle. Do not install it
into a headless profile: the harness fails the whole boot when a row stays
PENDING, so there is no harmless "inactive" state — the row is either
active or the boot refuses to start.The sidebar entry and panel mount on the sidebar.footer.action and
shell.overlay slots introduced in client packages 0.1.0-rc.5.
>=0.1.0-rc.5 <0.2 and resolves on npm today
(0.1.0-rc.6 is published for the runtime/layout/sidebar/slots packages).@deepseek-ai/dsh-web-app bundle itself is still not installable from
npm (one of its dependencies, @deepseek-ai/dsh-client-ui-model, is
unpublished), so a fresh dsh plugin add @deepseek-ai/dsh-web-app fails.
Until DeepSeek publishes it, install web-app from the harness source
checkout, or use a profile that already carries it.Dependencies install from npm; the repository is self-contained.
pnpm install # from the frozen lockfile
pnpm run check:ci # lint + typecheck (CI declarations) + tests + build
pnpm run check # same, but typecheck uses real harness types when a
# sibling deepseek-harness checkout exists (tsconfig paths)
pnpm run bootstrap # optional: clone + build the harness checkout for real types
pnpm pack --dry-run # inspect the published tarball contents
CI runs check:ci plus a real-boot smoke job on every push and pull request
(.github/workflows/ci.yml). The smoke job installs the bundle through the
community-standard dsh plugin add flow and exercises the control surface,
login gate, rate limiter, and index polyfill against a live harness
composition (scripts/smoke.mjs).
The package has a Host entry (lib/index.js) and an official DeepSeek Harness Client entry
(lib/client.js). The browser UI registers only through the official
sidebar.footer.action and shell.overlay slots. On the standard DeepSeek Harness sidebar
layout the action is promoted to its own full-width row above the other footer
actions — detected by layout, never through private APIs — and any unknown
layout falls back to the slot's native inline button. No private DeepSeek Harness DOM is
written.
All endpoints live under /dsh-reverse-proxy on the main DeepSeek Harness Web server, are
loopback-only, and are never forwarded through the public proxy. Mutations
require the x-dsh-reverse-proxy-control: 1 header and a loopback Origin.
| Method | Path | Body | Returns |
|---|---|---|---|
GET | /dsh-reverse-proxy/status | — | snapshot (enabled, running, target, backend, listen) |
GET | /dsh-reverse-proxy/token | — | { accessToken } |
POST | /dsh-reverse-proxy/start | — | snapshot |
POST | /dsh-reverse-proxy/stop | — | snapshot |
POST | /dsh-reverse-proxy/rotate-token | — | snapshot + new accessToken |
POST | /dsh-reverse-proxy/listen | { "host": "127.0.0.1", "port": 3081 } | snapshot (port 0 = pick a free port) |
GET | /dsh-reverse-proxy/sessions | — | { sessions: [{ id, label, status, createdAt, lastSeenAt }] } |
POST | /dsh-reverse-proxy/sessions/approve | { "id": "…" } | { "ok": true } (pending → active) |
POST | /dsh-reverse-proxy/sessions/revoke | { "id": "…" } | { "ok": true } (device loses access immediately) |
On the proxy itself, /dsh-reverse-proxy/healthz answers {"ok":true} and the
login page lives at /_dsh_reverse_proxy/login.
This plugin adds no model-visible prompt, tool, or session content. Token and proxy status exist only in the human Web control surface, so token and KV-cache effects are zero.
Secure because TLS usually terminates
outside the local proxy; deploy the tunnel with HTTPS and protect local
machine access.set-cookie and its own session cookie: correct
for today's DeepSeek Harness Web (loopback trust, no cookies), but a future DeepSeek Harness Web
feature that depends on browser cookies would need revisiting.loginMaxAttempts then a
429 lockout) on top of the fixed per-attempt delay; a 192-bit token makes
brute force impractical regardless, and rotating the token invalidates all
sessions. Shared-NAT users share one bucket — see loginLockoutSeconds.Contributions are welcome — see CONTRIBUTING.md for the development setup, checks, and conventions.
Security issues are handled privately — see SECURITY.md for the disclosure process and the supported-versions policy.
MIT © 2026 JUANWANG-BUAA
FAQs
Authenticated provider-neutral reverse proxy and mobile control UI for DeepSeek Harness Web
The npm package dsh-reverse-proxy receives a total of 0 weekly downloads. As such, dsh-reverse-proxy popularity was classified as not popular.
We found that dsh-reverse-proxy 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.

Security News
vlt 1.5.0 links skills from JavaScript dependencies to coding agents, with lockfile versioning and Socket data to filter out known malicious packages.

Security News
Rust 1.100 will add opt-in dependency cooldowns to Cargo, giving security scanners and maintainers time to catch malicious crate releases.

Security News
Cloudflare is acquiring Deno’s team, which will provide another year of bug fixes and security updates before ending support for the runtime.