
Security News
Deno Goes the Way of the Dinosaur
Cloudflare is acquiring Deno’s team, which will provide another year of bug fixes and security updates before ending support for the runtime.
dsh-web-startup-auth
Advanced tools
DSH remote-aware web-startup replacement + username/password auth plugin: allows --host 0.0.0.0 when paired with the auth plugin
中文 | English
DSH(DeepSeek Harness)远程 Web 启动 + 用户名/密码认证插件。
⚠️ 版本跟进声明:本项目只跟进官方 dsh 的正式发布通道(
nextdist-tag),不跟进alpha预览通道(当前基线:dsh 0.2.1-rc.2,依赖 5 个@deepseek-ai/dsh-*已 bump 到^0.2.1-rc.1(caret 在 0.2.1 线内自动解析到最新 rc);适配审查与观察哨见docs/upgrade-dsh-0.2.0-playbook.md)。0.2.1 线双时代兼容已落地并随 bump 生效(通配--host的 schema 拓窗、LAN 信任的官方消费路径、TLS/--public-url透传;在 0.2.1 之前的 dsh 上这些新 flag 会明确报错而非静默忽略)。

原版 @deepseek-ai/dsh-web-app/startup 出于安全考虑硬拒绝 --host 0.0.0.0;本插件替换它,并配一个带登录/注册页的认证插件,让 dsh web 可以在局域网(或任何非回环接口)上安全暴露浏览器界面。
--host 0.0.0.0 可用,替代原版启动器的硬性拒绝;具体 IP 字面量(如 --host 192.168.1.5、--host ::1、--host fd00::1)与通配 :: 同样可用(#35;非规范 IPv6 拼写自动规范化,带 zone 的(%eth0)与 IPv4-mapped(::ffff:a.b.c.d)写法拒绝)。纯 IPv6 网络下 0.0.0.0 只绑 IPv4、界面不可达;:: 在 Linux 默认双栈(net.ipv6.bindv6only=0),同时监听 IPv6 与 IPv4-mapped,比 0.0.0.0 覆盖更全;bindv6only=1 的系统上 :: 仅 IPv6。另透传上游两个启动能力(需 dsh ≥ 0.2.1):--public-url <url>(声明对外访问 URL)与 --tls-cert/--tls-key(直连 HTTPS,见「安全说明」);在低于 0.2.1 的 dsh 上使用会明确报错提示需要 dsh ≥ 0.2.1,而不是静默忽略。prefers-color-scheme)。Host 头都是回环时才免认证。所以本机浏览器直接访问 http://127.0.0.1:<端口>/ 无需注册或登录;局域网客户端、以及反向代理转发来的请求(Host 是公网域名)一律需要会话。免登录不等于已登录:本机没有会话 cookie,认证页显示的是「管理员账号」而不是「当前登录」,也不会给出退出登录入口(没有会话可退)。Retry-After。本机(真回环且未开启「本机登录校验」)豁免全局退避,避免攻击者借此把管理员锁在自己机器外面。dsh_sid,默认 14 天有效、可在设置面板调节(3–180 天档位),HttpOnly + SameSite=Lax;TLS 监听下自动追加 ; Secure)。/api/* 及第三方插件的 RPC 路由,除 /api/auth/* 与 /login)必须携带有效会话,否则返回 401/拒绝握手。crypto.randomUUID polyfill —— 非安全上下文下该 API 缺失,会导致所有 RPC 失败。dsh-auth-* 签名 cookie),/api 与 index.html 一律要求携带、连回环都不豁免(本机也得先换 token URL)。本插件为已通过自己认证(dsh_sid 会话,或 TCP 对端 + Host 双回环的本地请求)的访问者自动补发该 cookie:页面导航经一次 200 跳板(meta refresh 回原路径)即带上、登录响应直接下发(不用 3xx:重定向响应里新设的 cookie 不会带给重定向目标,补发会被逐跳重放成 ERR_TOO_MANY_REDIRECTS),全程无需接触启动打印的 token URL——「账号/密码 + 可撤销会话」仍是唯一认证入口,上游 cookie 只是通过上游闸门的凭据。本插件是一个 DSH bundle(package.json 的 dsh.bundle.patch 声明了随包分发的 cordis.patch.yml)。用 dsh plugin 安装后,包会被加入 profile 的 dsh.profile.bundles,补丁层自动生效,无需手动编辑任何配置文件。
# 方式一:从源码安装
git clone <仓库地址>
cd dsh-web-startup-auth
npm install # 安装构建依赖(typescript 等)
npm run build # 编译 src/ 到 lib/(插件运行时加载 lib/ 下的产物)
dsh plugin --profile web add .
# 方式二:从 npm registry 安装(已装过旧版本时执行同一条命令即可升级)
dsh plugin --profile web add dsh-web-startup-auth@latest
dsh plugin是 pnpm 转发器,--profile <name>必填;add .会把当前目录以link:方式装进 profile。
版本范围:本插件声明支持 dsh
>=0.1.7-rc.1、不支持0.3.0起的版本线(含其预发布版)。运行中的 dsh 超出范围时,dsh 会跳过本 bundle 并打印原因——这是刻意的 fail-loud:宁可不加载,也不在未适配验证过的 dsh minor 版本线上静默运行。注意粒度是 minor 线:同一条线内的后续版本(含 rc 等预发布)会照常加载,每出一条新 minor 线要先完成适配再考虑放宽范围。确需强行启用可走 profile 的 version exemption(插件管理器文档)。
启动:
dsh web --host 0.0.0.0
# 纯 IPv6 网络(或想同时覆盖 IPv6):
dsh web --host :: --port 8080
# 具体地址绑定(如只服务某块网卡):
dsh web --host 192.168.1.5
# 直连 HTTPS(需 dsh >= 0.2.1;自签证书同样可用,浏览器会提示不受信任):
dsh web --host 0.0.0.0 --tls-cert cert.pem --tls-key key.pem
安装时已自动应用补丁,无需再用
--patch叠加——重复叠加会把插件再插入一遍,导致重复。
http://<主机IP>:<端口>/(在本机则用 http://127.0.0.1:<端口>/,无需登录)。IPv6 地址在 URL 中必须加方括号:http://[<IPv6地址>]:<端口>/。注意:--host :: 启动时终端只打印回环 URL(上游的 LAN 地址推导只枚举 IPv4),局域网 IPv6 地址请用上面的形式手动拼接;打印的回环 URL 固定是 http://127.0.0.1:<端口>/(上游硬编码),bindv6only=1 的系统上 :: 是纯 IPv6 套接字、它不通,本机请用 http://[::1]:<端口>/。/login,显示"设置管理员账号密码"注册表单。/api/auth/logout 清除会话 cookie)。如果需要在本地设置账号密码(本机默认免登录,界面不会自动跳登录页):
http://127.0.0.1:<端口>/login —— 未注册时该页直接显示注册表单。注册后本机仍免登录;想让本机也要登录,到认证 → 登录要求打开「本机登录校验」(需先有账号)。开关打开后本机也要走 /login(页面会立即跳过去),登录后认证页才会显示「当前登录」和退出登录入口。
凭据与会话密钥保存在 $DSH_HOME/web-auth.json($DSH_HOME 未设置时即 ~/.dsh/web-auth.json,与 dsh 自身数据同目录;可用环境变量 DSH_WEB_AUTH_FILE 覆盖整个路径):
sessionMaxAgeDays,默认 14)也存在这个文件里,可在设置面板调节;调整只对新签发的会话生效。dsh --profile web auth-reset,交互式设置新密码(或 dsh --profile web auth-reset --password <新密码> 非交互)。重置会轮换会话密钥,所有已登录的浏览器都需要重新登录一次。dsh --profile web auth-reset --username <新用户名>(可与 --password 同用)。同样轮换会话密钥。用户名在注册/登录/修改时统一剥除 C0 控制字符(0x00–0x1F)与 DEL(0x7F)——旧版本若已把含 DEL 的用户名原样存盘,用它即可修复。$DSH_HOME/web-auth.json,默认 ~/.dsh/web-auth.json)并重启,即可重新注册。这只影响登录状态——已登录的浏览器需要再登录一次,不会删除任何会话记录或历史数据(它们存在 ~/.dsh/sessions/ 等位置,与本文件无关)。auth-reset 不能用来首次创建账号:它要求已有凭据,否则报「尚未注册管理员账号,无需重置」。首次只能用上面的注册页。Q:怎么在本地设置账号密码?必须代理到公网才能配置吗?
不需要,代理到公网不是前提。本机默认免登录(不会自动跳登录页),所以请在浏览器手动打开 http://127.0.0.1:<端口>/login——未注册时这一页直接显示注册表单;或者进设置面板 → 认证,页顶「尚未设置管理员账号」处点「前往设置管理员账号」。注意命令行 dsh --profile web auth-reset 只能改已有账号的密码/用户名,不能用来首次建号。
Q:本机不想登录,远程才要登录,可以吗?
这就是默认行为。设置面板 → 认证 → 登录要求默认关闭,即本机(真回环)免登录;远程客户端一律需要会话。打开这个开关(需先有管理员账号)则本机也强制登录,适合多人共用一台服务器时禁止同机其他账号免登录。没有「受信主机免登录」这种开关,--trusted-host 也不参与认证判断。
Q:忘记密码 / 想改用户名?
dsh --profile web auth-reset # 交互式
dsh --profile web auth-reset --password <新密码> # 非交互
dsh --profile web auth-reset --username <新用户名>
都会轮换会话密钥,所有已登录的浏览器需要重新登录一次。兜底方案是删掉凭据文件($DSH_HOME/web-auth.json,默认 ~/.dsh/web-auth.json)再重启重新注册——不影响历史会话数据。
Q:访问某个接口返回 403,是本插件拦的吗?
本插件的认证失败只会返回 401 或者跳转到登录页,从不返回 403。所以看到 403 先看响应体的形状来定位来源:
| 响应体 | 来源 | 怎么办 |
|---|---|---|
401,或页面被送到 /login | 本插件(会话无效) | 重新登录 |
纯文本 forbidden | 上游 dsh 的 Host 信任围栏 | 检查反向代理是否保留了真实 Host,必要时加 --trusted-host <域名> |
{"error":"request-not-trusted"} | 第三方插件自带的回环限制 | 见下一条 |
transport failure ... HTTP 403 | 第三方插件自带的回环限制 | 见下一条 |
Q:第三方插件(如 dsh-im、dsh-workbuddy-connect)在局域网返回 403?
这是该插件给它自己的接口加的回环地址限制(只放行 127.0.0.1 / localhost),与本插件和你的服务器都无关——本插件只管 /api/* 的会话闸门,管不到别的插件挂在 webServer 上的路由。
cordis.patch.yml 里加 rpcAuthority: trusted-host;新版已默认放行,一般不用配。dsh-workbuddy-connect):只能去该插件的仓库提 issue,请求提供一个可配置的等价开关。临时绕过办法是在你自己的电脑上做一次 SSH 端口转发,让浏览器通过回环地址访问,限制就不会触发:
ssh -L 3080:127.0.0.1:3080 用户名@<服务器IP>
保持这个窗口不关,浏览器打开 http://127.0.0.1:3080 即可。注意此时所有请求的 Host 都是回环,会被当作本机访问——不要在不受信任的网络上这么做。
Q:设置面板报「加载提供方目录失败 / settings are unavailable in this browser」?
最常见的原因是装到了旧版本。这个症状在 0.1.1 就已修好,0.1.5 起换了实现(远程浏览器下 settings 面板正常渲染)。先确认版本:
dsh plugin --profile web add dsh-web-startup-auth@latest
add 时务必带 @latest:不带的话 pnpm 会一直复用首次写入的版本号,之后用 update 也升不上去(历史上因此排查过多次)。
Q:升级 dsh 之后插件行为异常?
npm run build,然后重启 dsh web(lib/ 是入库的构建产物,不构建等于没改)。add dsh-web-startup-auth@latest。>=0.1.7-rc.1,不支持 0.3.0 起的版本线。超出范围时 dsh 会跳过本 bundle 并在启动日志里打印原因(刻意的 fail-loud),在启动日志里搜 skipped 就能确认。Q:登录页和首页来回循环跳转 / Safari 报 ERR_TOO_MANY_REDIRECTS?
/login 互跳的死循环:0.1.3 起已修复(0.1.2 的认证判定只看启动参数、不看请求本身,反代场景下会误判)。两者如果仍出现,先确认装的是最新版,清一下该站点的 cookie 再试。
Q:拼图验证能挡住脚本吗?
挡不住,如「特性」一节所说——答案就画在图上,脚本几十行就能读出来。当个乐子,别当安全边界。
如果您在寻找开箱即用的专为 Agent 时代研发的 IDE,推荐您使用 Omniterm
--tls-cert/--tls-key 直连 HTTPS——此时会话 cookie 与补发的原生 cookie 自动携带 ; Secure(低于 0.2.1 的 dsh 无此能力,使用时会明确报错提示需要 dsh ≥ 0.2.1)。crypto.scryptSync,无第三方依赖。dsh_sid 是自包含签名 cookie,/api/auth/logout 只清除浏览器一侧的 cookie。cookie 一旦泄露(如明文 HTTP 下被嗅探),在有效期内无法单独吊销(上限即设置面板所选的会话有效期档位)。例外:dsh --profile web auth-reset、设置面板的「修改密码」与「修改用户名」都会轮换会话密钥,一次性让所有已登录的浏览器重新登录(操作者自己的当前会话由服务端重新签发,保持登录)。/api/auth/login、/api/auth/change-password 与 /api/auth/change-username(旧密码/当前密码错误同样计次)。如需更严格防护请在反向代理层增加通用限速。connection/request 扩展点上的会话闸门。两层互为保险:上游接口变化导致其中一层失效时,另一层仍保证只有可撤销的会话(或真本机回环)能访问 API——30 天不可单独吊销的上游原生 cookie 永远不能单独作为 API 凭据。$DSH_HOME/web-auth.json(默认 ~/.dsh/web-auth.json;含密码哈希与会话签名密钥)以 0600 保存,目录以 0700 创建;插件启动时会自动修复旧版本遗留的过宽权限。--trusted-host:该参数透传给上游 dsh 的 Host 信任围栏(connection 的 trustedHosts),不参与本插件认证判断——远程客户端一律需要有效会话,不存在"受信主机免登录"。127.0.0.1,由代理做 SSL 卸载并转发。此时代理必须转发真实 Host(nginx 默认即为 proxy_set_header Host $host;,配上 --trusted-host <域名> 让 DSH 自身的 Host 围栏放行);认证通过后插件按请求的真实 Host(公网域名)补发上游原生浏览器 cookie,上游闸门据此放行。反之,若代理把 Host 写死成 127.0.0.1,插件会认为请求来自本机从而放行全部流量、不做认证——不要这样配置。X-Forwarded-For 不被采信(客户端可伪造),信任判定只看 TCP 对端地址与 Host。connection.isLoopback,远程浏览器下的 settings mirror 走内存模式、插件配置卡片与 Models 页不可用;本插件当时通过 webServer.tapIndex 注入脚本在 connection 激活瞬间把该标志覆盖为恒 true。0.1.2 上游引入真实 cookie 认证后能进 UI,但 settings mirror 仍按同一标志判定——LAN 浏览器依旧得到从不读 host 的 memory mirror,设置面板的 Models(提供方目录)会报 "settings are unavailable in this browser"。直接恢复旧的 getter 覆盖会破坏 web boot(A/B 实测 26 个前端插件 pending),因此 0.1.2 起改用注入 window.__DSH_TRANSPORT__ = { ownsHost: true }:connection client 构造时据此把 isLoopback 报为 true(api/rpc 字段缺省时安全回退,且不重写 cordis 服务),LAN 与回环浏览器的全部设置面(含 Models)都正常渲染。当前保留的浏览器侧 shim:该 transport hook 与 crypto.randomUUID polyfill(明文 HTTP 非安全上下文所需)。npm install
npm run typecheck # tsc --noEmit
npm test # vitest
npm run build # tsc -p tsconfig.json + tsdown,产物输出到 lib/
tsc 编译 node 侧源码(src/*.ts)与类型声明到 lib/、lib/types/。tsdown 把前端插件(src/client/index.tsx)打包成浏览器 bundle lib/client.js(window.__ModuleLoader__.load 注册格式)。改前端代码后必须重新构建,profile 里 link: 安装会自动加载新产物。@deepseek-ai/dsh-client-* 包只用于类型与构建,运行时由 DSH 前端模块表提供。FAQs
DSH remote-aware web-startup replacement + username/password auth plugin: allows --host 0.0.0.0 when paired with the auth plugin
The npm package dsh-web-startup-auth receives a total of 123 weekly downloads. As such, dsh-web-startup-auth popularity was classified as not popular.
We found that dsh-web-startup-auth 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
Cloudflare is acquiring Deno’s team, which will provide another year of bug fixes and security updates before ending support for the runtime.

Security News
Anthropic’s free OSS Scanner uses Mythos and other Claude models to find open source vulnerabilities and send maintainers reports with proposed fixes.

Security News
On Front Lines’ Early Adopters: CISO podcast, Andrew Becherer shares lessons from Datadog, weighs the long-term costs of AI-built tools, and explains how founders can actually gain a CISO’s trust.