← 返回列表
未验证
为公网部署的 Agent 加上登录认证与访问控制
尚未跑自动兼容性验证,可查看页面内的依赖与入口分析。 · 最近上游提交 2026/8/21 · 已提供中文文档
DeepSeek Harness 的身份验证与安全加固插件
综合分
28.1
GitHub 分
28.1
用户评分
—
★ Stars
1
周下载量
—
安装插件(需先安装 dsh CLI 引擎:npm install -g @deepseek-ai/dsh)
dsh plugin --profile web add zephaniahwang94-cmyk/dsh-auth-gate该插件未发布到 npm,走 GitHub 源安装(pnpm 若拦截 prepare 脚本,按其提示在 pnpm-workspace.yaml 的 allowBuilds 中放行后重跑)
数据截至 2026/9/16(元数据每日更新 · 实装验证按队列轮转,单条结论的验证时间见上方)
依赖的 DSH / Cordis 模块
@deepseek-ai/cordis@deepseek-ai/dsh-host-webserver用户评分
还没有人投票,来当第一个
订阅周报,不错过优质插件更新
每周一封 · 高评分插件 + 新用户活动
README
dsh-auth-gate
DeepSeek Harness 的认证与安全加固插件。
公网 / Docker 部署中的安全风险
DeepSeek Harness 被设计为本地开发工具。其默认安全模型依赖回环绑定(127.0.0.1)和请求头校验(Host / Origin / Sec-Fetch-Site)。该模型在以下几种常见部署场景中会失效:
场景 1:Docker 容器部署
常见的 Dockerfile 模式
EXPOSE 3080
CMD ["npx", "@deepseek-ai/dsh", "web"]
重要更正:仅 EXPOSE 本身不会暴露任何内容,且 Docker 端口发布通常无法访问仅绑定到容器回环接口的进程。只有当 DSH 被配置/修改为绑定 0.0.0.0,或者容器内的另一个进程将面向容器的端口代理到 DSH 时,风险才会出现。此时,若发布该端口时未限制主机 IP(例如 -p 3080:3080),则会将完整的 Agent 控制平面暴露给可达网络。
根本原因:没有认证层。信任围栏仅校验请求头,而不校验调用方身份。
场景 2:反向代理(Nginx / Caddy)
server {
listen 80;
server_name dsh.example.com;
location / {
proxy_pass http://127.0.0.1:3080;
proxy_set_header Host $host;
proxy_set_header Origin $http_origin;
}
}
风险:反向代理会转发来自客户端的 Host 和 Origin 请求头。信任围栏看到匹配的请求头后便允许该请求。任何能够访问反向代理的人都可以获得完整访问权限。
根本原因:信任围栏校验的是请求头,而不是网络来源。透传 Host/Origin 的代理会绕过该围栏。
场景 3:云虚拟机 / CI 运行器
在具有公网 IP 的云虚拟机上运行
dsh --profile headless "deploy the app"
风险:如果虚拟机的防火墙配置错误,或者服务绑定到 0.0.0.0(未来功能),则 Agent 可被远程访问。被攻陷的 Agent 可以在虚拟机上执行任意代码。
根本原因:没有认证,除绑定之外没有网络级别的访问控制。
场景 4:团队共享实例
在办公室服务器上为团队运行
DSH_AUTH_TOKEN="" dsh web --host 0.0.0.0 # 未来:当支持 0.0.0.0 时
风险:所有团队成员共享同一个 Agent 实例。一个用户的恶意提示词可能影响另一个用户的会话。没有记录谁做了什么的审计追踪。
根本原因:没有用户身份,没有会话隔离,没有审计日志。
信任围栏实际保护的内容
| 检查项 | 作用 | 不做什么 |
|-------|-------------|-------------------|
| Host 请求头 | 阻止 DNS 重绑定攻击 | 不验证调用方是否为本地 |
| Sec-Fetch-Site | 阻止来自浏览器的跨站请求 | 不阻止 curl、脚本或非浏览器客户端 |
| Origin 头 | 阻止跨源浏览器请求 | 不阻止没有 Origin 头的请求 |
信任围栏是一种浏览器 CSRF 防御,而非身份验证层。它能阻止恶意网站向你的本地 DSH 实例发起请求。它无法阻止任何能够直接通过 HTTP 连接到该端口的人。
本插件的缓解措施
| 风险 | 缓解措施 | 覆盖范围 |
|------|-----------|----------|
| 未授权的 API 访问 | Bearer 令牌 + 会话登录 | HTTP + WebSocket 路由 |
| 过多的审批提示 | 前置的按会话瀑布式限流器 | 到达此监听器的审批 |
| 暴露的 0.0.0.0 | 故障关闭式身份验证网关 | HTTP + WebSocket |
| Windows 部分沙箱 | 已记录,无法在插件层面修复 | — |
本插件不修复的内容
1. ACP / SDK 通道:这些通道通过 stdio(stdin/stdout)运行,而非 HTTP。无法通过网络访问,但如果进程被共享,也同样不受保护。
2. 无用户隔离:所有已认证用户共享同一个 Agent 实例和会话池。没有按用户划分的沙箱。
3. 无审计日志:本插件不记录谁进行了身份验证或做了什么。DSH 会话日志记录 agent 操作,但不记录其背后的人类身份。
4. 审批监听器顺序:限流器被前置,但 Cordis 允许后续插件在其前面再前置另一个短路应答器。请将限流器视为纵深防御,而非不可绕过的策略边界。
5. 反向代理登录桶:登录尝试以 TCP 对端地址为键。在反向代理后面,用户共享代理的桶;请同时配置边缘速率限制。本插件有意不信任可伪造的转发头。
本插件同时包装现有的和未来的 DSH HTTP/upgrade 路由。由于当前 DSH 暴露的是注册表而非中间件,如果该内部契约发生变化,启动会故障关闭。
安装并选择保护方式
安装一次并选择一个预设。凭据保留在环境变量中,绝不会写入补丁文件。两个安装程序都会引导依赖项、构建插件、在选定的 Harness 配置文件中注册它,并打印可复用的启动命令。
Linux / macOS
git clone https://github.com/zephaniahwang94-cmyk/dsh-auth-gate.git
cd dsh-auth-gate
export DSH_AUTH_USERNAME=admin
printf 'Password (12+ characters): ' >&2
stty -echo; IFS= read -r DSH_AUTH_PASSWORD; stty echo; printf '\n' >&2
export DSH_AUTH_PASSWORD
Required when the public URL uses HTTPS:
export DSH_AUTH_SECURE_COOKIE=true
./install.sh --protection Full
当只需要该保护时,使用 NetworkAuth 或 ApprovalLimit 代替 Full。添加 --start 可立即启动 Harness,添加 --profile NAME 可使用另一个配置文件,或添加 --harness-path /path/to/deepseek-harness 以使用源码检出。
Windows PowerShell
$env:DSH_AUTH_USERNAME = 'admin'powershell
$env:DSH_AUTH_PASSWORD = Read-Host 'Enter a private password (12+ characters)'
Required when the public URL uses HTTPS:
$env:DSH_AUTH_SECURE_COOKIE = 'true'
.\install.ps1 -Protection Full
.\install.ps1 -Protection NetworkAuth
.\install.ps1 -Protection ApprovalLimit
如果 dsh 不在 PATH 中,任一安装程序都会自动使用同级的 deepseek-harness 源代码检出。如果两者都不存在,则回退到官方 npx @deepseek-ai/dsh CLI。如需使用其他源代码位置,请传入 -HarnessPath C:\path\to\deepseek-harness 或 --harness-path /path/to/deepseek-harness。
Full 是默认值。添加 -Start 可立即启动。否则脚本会打印出确切的可复用启动命令。在后续启动时继续使用其 --patch 参数:
powershell
dsh --profile web --patch C:\path\to\dsh-auth-gate\presets\full.yml
| 预设 | HTTP + WebSocket 认证 | 审批限流器 | 重要后果 |
|---|---:|---:|---|
| Full | 是 | 是 | 推荐 |
| NetworkAuth | 是 | 否 | 审批提示不受速率限制 |
| ApprovalLimit | 否 | 是 | 网络控制界面仍未经认证 |
HTTP 和 WebSocket 认证无法拆分。这可防止出现已认证的 UI 却暴露 RPC 升级通道的情况。现有的顶层配置仍然兼容,并且在缺少 protections 时表示完全保护。
初始密码与协作者
终端用户
在启动 Harness 的同一进程环境中设置凭据。不要将真实密码放入 YAML 或命令行参数中。
powershell
cd C:\path\to\deepseek-harness
$env:DSH_AUTH_USERNAME = 'admin'
$env:DSH_AUTH_PASSWORD = Read-Host 'Enter a private password (12+ characters)'
$env:DSH_AUTH_SECURE_COOKIE = 'false' # local HTTP only; use true with HTTPS
pnpm dsh web
在 Linux 上,请在 shell 中导出相同的变量,或将它们提供给启动 Harness 的服务管理器。避免将密码直接放入 shell 历史记录。对于 systemd,请使用仅 root/用户可读的 EnvironmentFile(chmod 600),并在 Harness 单元中引用它;轮换凭据后重启该单元。环境变量可能会被具有相同操作系统身份的其他进程读取,因此对于共享主机,请使用专用服务账户。
环境变更不会影响已在运行的进程。更改密码后请重启 Harness。由于会话签名密钥在每次启动时生成,每次重启都会使所有浏览器会话退出登录。
Windows 上仅使用 WebUI 的用户
首个密码无法在受保护的 WebUI 内安全创建:认证必须在页面能够打开之前就已存在。请使用 开始 → 编辑账户的环境变量,创建 DSH_AUTH_USERNAME、DSH_AUTH_PASSWORD 和 DSH_AUTH_SECURE_COOKIE,然后完全退出并重新打开 Harness WebUI 启动器。用户环境变量由 Windows 存储,可能会被以相同操作系统用户身份运行的其他进程读取;请仅在受信任的本地账户上使用此方式。
协作者账户
版本 1.2 仅支持一个共享登录身份。它无法创建第二个独立命名的协作者账户,也无法将操作归因于不同的人。共享主密码可以授予访问权限,但这并不是独立账户,并且不建议在不受信任的团队中使用。
对于临时的受信任协作者,请轮换共享密码、重启 Harness、通过安全渠道共享密码,然后在访问应结束时再次轮换并重启。对于长期协作者,请使用单独的 Harness 实例/操作系统身份,或使用为每个人分配一个身份的身份验证反向代理。不要声称实现了按用户隔离:经过身份验证的用户仍然共享同一个 Agent、会话、工作区权限和审计身份。
配置
Bearer Token 模式
适用于脚本和非浏览器客户端。HTTP 和 WebSocket 请求必须包含 Authorization: Bearer ,并且令牌必须至少为 32 字节。浏览器 WebSocket API 无法设置此标头,因此对于 Web UI,请使用 session 或 both。
选项 A:环境变量
powershell
$env:DSH_AUTH_TOKEN = [Convert]::ToHexString(
[Security.Cryptography.RandomNumberGenerator]::GetBytes(32)
).ToLowerInvariant()
dsh web
选项 B:配置(不推荐,因为配置诊断可能会暴露它)
yaml
config:
mode: bearer
Deliberately empty: generate a private token; never copy a documented value.
token: ''
用法:
sh
Denied
curl http://127.0.0.1:3080/api
→ 401 Unauthorized
Allowed
curl -H "Authorization: Bearer $env:DSH_AUTH_TOKEN" http://127.0.0.1:3080/api
→ 200 OK
Session 模式
带有用户名/密码的登录页面,使用会话 cookie。
yaml
config:
mode: session
Omit credentials here; set DSH_AUTH_USERNAME and DSH_AUTH_PASSWORD.
sessionTtl: 3600
loginPath: /auth/login
访问 http://127.0.0.1:3080/auth/login 进行登录。该 cookie 为 HttpOnly; SameSite=Strict。对于 HTTPS/公开部署,请设置 secureCookie: true;仅在直接本地 HTTP 场景下将其保留为 false。
两种模式
yaml
config:
mode: both
Omit credentials here; set DSH_AUTH_TOKEN, DSH_AUTH_USERNAME,
and DSH_AUTH_PASSWORD in the process environment.
Bearer token 用于 API/脚本访问,登录页面用于浏览器访问。
沙箱升级速率限制
yaml
config:
approvalRateLimit:
maxPerMinute: 3
maxPerSession: 10
超出的请求会以 'unavailable' 拒绝(故障关闭)。
配置参考
| 字段 | 类型 | 默认值 | 描述 |
|-------|------|---------|-------------|
| mode | 'bearer' \| 'session' \| 'both' | 'bearer' | 身份验证模式 |
| protections.networkAuth | boolean | true | 启用不可分割的 HTTP + WebSocket 身份验证 |
| protections.approvalRateLimit | boolean | true | 启用审批瀑布流速率限制 |
| auth | object | — | 以下所有身份验证字段的可选嵌套形式 |
| token | string | 环境变量 DSH_AUTH_TOKEN | Bearer 令牌 |
| sessionSecret | 不支持 | 每次启动随机生成 | 持久化密钥会被拒绝,因此登出后的 Cookie 无法在重启后恢复 |
| sessionTtl | number | 3600 | 会话生命周期(秒) |
| loginPath | string | '/auth/login' | 登录页面 URL 路径 |
| username | string | — | 会话登录用户名 |
| password | string | — | 会话登录密码 |
| secureCookie | boolean | false | 为 Cookie 添加 Secure;启用 HTTPS 时开启 |
| approvalRateLimit.maxPerMinute | number | 3 | 每分钟最大升级请求数 |
| approvalRateLimit.maxPerSession | number | 10 | 每个会话最大升级请求数 |
Bearer 令牌必须至少为 32 字节。登录尝试限制为每个源地址每分钟五次。每次启动都会生成新的会话密钥,并使旧的浏览器会话失效;持久化密钥会被拒绝,因为登出撤销被有意设计为进程本地。
架构
HTTP / WebSocket 请求
↓
AuthGateway(精确、前缀、回退和升级路由)
├─ /auth/login → 登录页面处理器
├─ /auth/logout → 登出处理器
└─ /* → 认证检查
├─ Authorization: Bearer → validateBearer()
├─ Cookie: dsh_session= → validateSession()
└─ 无有效认证 → 401 / 重定向到登录
审批请求(approval/request 瀑布流)
↓
RateLimiter
├─ 从 req.agent.session.id 解析会话
├─ 未超限 → 委托给下一个应答者
└─ 超限 → 'unavailable'(拒绝)
开发
sh
npm install
npm run typecheck
npm run build
npm test
许可证
MIT。请按照 SECURITY.md 报告安全问题。
中文
DeepSeek Harness 的 认证与安全加固插件。
公网部署 / Docker 部署的安全隐患
DeepSeek Harness 的定位是本地开发工具。它的默认安全模型依赖 loopback 绑定(127.0.0.1)和请求头校验(Host / Origin / Sec-Fetch-Site)。在以下常见部署场景中,这个模型会失效:
场景一:Docker 容器部署
dockerfile
常见的 Dockerfile 写法
EXPOSE 3080
CMD ["npx", "@deepseek-ai/dsh", "web"]
重要更正:EXPOSE 本身不会暴露端口,Docker 端口发布通常也无法访问只绑定在容器 loopback 上的进程。只有当 DSH 被配置/修改为绑定 0.0.0.0,或容器内另有进程把对外端口代理到 DSH 时才出现风险。此时若使用未限制宿主 IP 的 -p 3080:3080,完整的 Agent 控制面会暴露给可达网络。
根因:没有认证层。信任围栏只校验请求头,不验证调用者身份。
场景二:反向代理(Nginx / Caddy)
nginx
server {
listen 80;
server_name dsh.example.com;
location / {
proxy_pass http://127.0.0.1:3080;
proxy_set_header Host $host;
proxy_set_header Origin $http_origin;
}
}
隐患:反向代理会把客户端的 Host 和 Origin 头原样转发。信任围栏看到匹配的 header 就放行。任何能访问反向代理的人,都拥有完整权限。
根因:信任围栏校验的是 header,不是网络来源。透传 Host/Origin 的代理会让围栏失效。
场景三:云服务器 / CI 运行器
sh
在有公网 IP 的云服务器上运行
dsh --profile headless "deploy the app"
隐患:如果服务器防火墙配置不当,或者未来 DSH 支持 0.0.0.0 绑定,Agent 会被远程访问。被攻破的 Agent 可以在服务器上执行任意代码。
根因:没有认证,绑定之外没有网络层访问控制。
场景四:团队共享实例
sh
在办公室服务器上跑给团队用
DSH_AUTH_TOKEN="" dsh web --host 0.0.0.0 # 未来支持时
隐患:所有团队成员共享同一个 Agent 实例。一个用户的恶意 prompt 可以影响其他用户的 session。没有审计日志记录谁做了什么。
根因:没有用户身份,没有 session 隔离,没有审计日志。
信任围栏实际保护了什么
| 检查项 | 做了什么 | 没做什么 |
|--------|---------|---------|
| Host header | 阻止 DNS rebinding 攻击 | 不验证调用者是否在本地 |
| Sec-Fetch-Site | 阻止浏览器的跨站请求 | 不阻止 curl、脚本、非浏览器客户端 |
| Origin header | 阻止浏览器的跨域请求 | 不阻止没有 Origin header 的请求 |
信任围栏是一个浏览器 CSRF 防御,不是认证层。它能阻止恶意网站向你的本地 DSH 发请求,但无法阻止任何能直接 HTTP 连接到该端口的人。
本插件的缓解措施
| 风险 | 缓解措施 | 覆盖范围 |
|------|---------|---------|
| 未授权 API 访问 | Bearer token + 登录页 | HTTP + WebSocket 路由 |
| 过量审批提示 | 前置的按会话 waterfall 限流 | 能到达该监听器的审批请求 |
| 暴露 0.0.0.0 | fail-closed 认证网关 | HTTP + WebSocket |
| Windows 沙箱不完整 | 已文档化,插件层无法修复 | — |
本插件无法修复的问题
1. ACP / SDK 通道:走 stdio(stdin/stdout),不走 HTTP。网络上不可达,但如果进程被共享则无法保护。
2. 没有用户隔离:所有认证用户共享同一个 Agent 实例和 session 池,没有 per-user 沙箱。
3. 没有审计日志:本插件不记录谁认证了、做了什么。DSH session 日志记录 Agent 行为,但不记录背后的人类身份。
4. 审批监听器顺序:限流器会 prepend,但 Cordis 允许后加载的插件再次 prepend 并在其前方短路。该限流器属于纵深防御,不是不可绕过的策略边界。
5. 反向代理登录桶:登录尝试按 TCP 对端地址计数;反向代理后的用户会共享代理的桶,因此还应配置边缘限流。本插件刻意不信任可伪造的转发请求头。
插件会包装 DSH 已有和以后注册的 HTTP/upgrade 路由。由于当前 DSH 暴露的是注册表而非 middleware,一旦内部契约变化,插件会 fail closed 并拒绝启动。
安装并选择防护类型
插件只安装一次,通过预设选择防护模块。凭据只从环境变量读取,不会写入 patch 文件。两个安装器都会自动安装依赖、构建插件、注册到指定 Harness profile,并输出可重复使用的启动命令。
Linux / macOS
sh
git clone https://github.com/zephaniahwang94-cmyk/dsh-auth-gate.git
cd dsh-auth-gate
export DSH_AUTH_USERNAME=admin
printf '请输入密码(至少 12 个字符): ' >&2
stty -echo; IFS= read -r DSH_AUTH_PASSWORD; stty echo; printf '\n' >&2
export DSH_AUTH_PASSWORD
公网 URL 使用 HTTPS 时必须设置:
export DSH_AUTH_SECURE_COOKIE=true
./install.sh --protection Full
只需要单项防护时可将 Full 改为 NetworkAuth 或 ApprovalLimit。添加 --start 可立即启动,--profile NAME 可选择其他 profile,源码仓库位于其他位置时使用 --harness-path /path/to/deepseek-harness。
Windows PowerShell
powershell
$env:DSH_AUTH_USERNAME = 'admin'
$env:DSH_AUTH_PASSWORD = Read-Host '请输入私有密码(至少12个字符)'
公网 URL 使用 HTTPS 时必须设置:
$env:DSH_AUTH_SECURE_COOKIE = 'true'
.\install.ps1 -Protection Full
.\install.ps1 -Protection NetworkAuth
.\install.ps1 -Protection ApprovalLimit
如果 dsh 不在 PATH,两个脚本都会优先使用同级的 deepseek-harness 源码仓库;两者都不存在时,自动回退到官方 npx @deepseek-ai/dsh CLI。源码位于其他目录时,分别传入 -HarnessPath C:\path\to\deepseek-harness 或 --harness-path /path/to/deepseek-harness。
默认是 Full。添加 -Start 可立即启动;否则脚本会输出准确的启动命令,例如:
powershell
dsh --profile web --patch C:\path\to\dsh-auth-gate\presets\full.yml
| 预设 | HTTP + WebSocket 认证 | 审批限流 | 重要后果 |
|---|---:|---:|---|
| Full | 是 | 是 | 推荐 |
| NetworkAuth | 是 | 否 | 审批提示不受本插件限流 |
| ApprovalLimit | 否 | 是 | 网络控制面仍无认证 |
HTTP 和 WebSocket 认证不可拆分,避免 UI 已认证但 RPC upgrade 裸露。旧版顶层配置继续兼容;没有 protections 时等同完整防护。
初始密码与协作者
终端用户
在启动 Harness 的同一个进程环境中设置凭据,不要把真实密码写进 YAML 或命令行参数。
powershell
cd C:\path\to\deepseek-harness
$env:DSH_AUTH_USERNAME = 'admin'
$env:DSH_AUTH_PASSWORD = Read-Host '请输入私有密码(至少12个字符)'
$env:DSH_AUTH_SECURE_COOKIE = 'false' # 仅本机 HTTP;HTTPS 必须为 true
pnpm dsh web
环境变量修改不会影响已经运行的进程;修改密码后必须重启 Harness。每次启动都会生成新的 session 签名密钥,因此重启也会让全部浏览器会话退出。
Linux 用户可在当前 shell 中导出相同变量,或交给启动 Harness 的服务管理器。不要把密码直接写入 shell 历史。使用 systemd 时,应将变量放入权限为 600 的 EnvironmentFile 并由 Harness unit 引用;轮换密码后重启 unit。同一操作系统身份的其他进程可能读取环境变量,因此共享主机建议使用独立服务账户。
只使用 WebUI 的 Windows 用户
首次密码不能安全地在受保护的 WebUI 内创建,因为页面开放前认证就必须存在。打开 开始菜单 → 编辑账户的环境变量,新增 DSH_AUTH_USERNAME、DSH_AUTH_PASSWORD 和 DSH_AUTH_SECURE_COOKIE,然后彻底退出并重新打开 Harness WebUI 启动器。Windows 会保存用户环境变量,同一操作系统用户运行的其他进程可能读取它们,因此只适用于可信的本机账户。
协作者账户
1.2 版本目前只支持一个共享登录身份,不能创建第二个独立命名的协作者账户,也不能把操作归因到不同人员。共享主密码虽然可以访问,但不属于独立账户,不建议用于互不信任的团队。
临时可信协作者可使用以下流程:轮换共享密码并重启 Harness,通过安全渠道发送密码;协作结束后再次轮换并重启。长期协作者应使用独立 Harness 实例/操作系统身份,或在前方部署支持每人独立身份的认证反向代理。即使认证通过,用户仍共享 Agent、session、workspace 权限和审计身份,不具备 per-user 隔离。
配置
Bearer Token 模式
用于脚本及非浏览器客户端。HTTP 和 WebSocket 请求都必须带 Authorization: Bearer ,token 至少 32 字节。浏览器 WebSocket API 无法设置该请求头,因此 Web UI 请使用 session 或 both。
方式一:环境变量
powershell
$env:DSH_AUTH_TOKEN = [Convert]::ToHexString(
[Security.Cryptography.RandomNumberGenerator]::GetBytes(32)
).ToLowerInvariant()
dsh web
方式二:配置文件
yaml
config:
mode: bearer
故意留空:请生成私有随机 token,不要复制文档中的固定值。
token: ''
验证:
sh
无 token → 拒绝
curl http://127.0.0.1:3080/api
→ 401 Unauthorized
有 token → 放行
curl -H "Authorization: Bearer $env:DSH_AUTH_TOKEN" http://127.0.0.1:3080/api
→ 200 OK
Session 模式
带登录页面,用户名密码验证后发 session cookie。
yaml
config:
mode: session
此处不写凭据;请设置 DSH_AUTH_USERNAME 和 DSH_AUTH_PASSWORD。
sessionTtl: 3600
loginPath: /auth/login
访问 http://127.0.0.1:3080/auth/login 登录。Cookie 设置为 HttpOnly; SameSite=Strict。HTTPS/公网部署必须设置 secureCookie: true;仅本机直接 HTTP 调试时保持 false。
两者同时启用
yaml
config:
mode: both
此处不写凭据;请在进程环境中设置 DSH_AUTH_TOKEN、
DSH_AUTH_USERNAME 和 DSH_AUTH_PASSWORD。
API/脚本用 token,浏览器用登录页。
沙箱升级速率限制
yaml
config:
approvalRateLimit:
maxPerMinute: 3
maxPerSession: 10
超限请求直接拒绝,返回 'unavailable'(fail-closed)。
配置参考
| 字段 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| mode | 'bearer' \| 'session' \| 'both' | 'bearer' | 认证模式 |
| protections.networkAuth | boolean | true | 启用不可拆分的 HTTP + WebSocket 认证 |
| protections.approvalRateLimit | boolean | true | 启用审批 waterfall 限流 |
| auth | object | — | 下列认证字段也可统一写在此对象中 |
| token | string | 环境变量 DSH_AUTH_TOKEN | Bearer token |
| sessionSecret | 不支持 | 每次启动随机生成 | 拒绝持久密钥,避免已注销 Cookie 在重启后复活 |
| sessionTtl | number | 3600 | Session 有效期(秒) |
| loginPath | string | '/auth/login' | 登录页路径 |
| username | string | — | 登录用户名 |
| password | string | — | 登录密码 |
| secureCookie | boolean | false | 为 Cookie 添加 Secure;HTTPS 必须启用 |
| approvalRateLimit.maxPerMinute | number | 3 | 每分钟最大升级请求数 |
| approvalRateLimit.maxPerSession | number | 10 | 每 session 最大升级请求数 |
Bearer token 必须至少 32 字节。登录尝试按来源地址限制为每分钟 5 次。每次启动都会生成新 session secret 并使旧浏览器会话失效;由于注销状态只在进程内保存,持久密钥会被拒绝。
架构
HTTP / WebSocket 请求
↓
认证网关(exact、prefix、fallback 和 upgrade 路由)
├─ /auth/login → 登录页处理
├─ /auth/logout → 登出处理
└─ /* → 认证检查
├─ Authorization: Bearer → validateBearer()
├─ Cookie: dsh_session= → validateSession()
└─ 无有效认证 → 401 / 重定向到登录页
审批请求(approval/request waterfall)
↓
速率限制器
├─ 从 req.agent.session.id 获取会话
├─ 未超限 → 交给下一个审批处理器
└─ 超限 → 'unavailable'(拒绝)
开发
sh
npm install
npm run typecheck
npm run build
npm test
许可证
MIT。安全漏洞请按照 SECURITY.md 私下报告。扫码进群