docs(dashboard-auth): remove legacy session-token references
Sweeps user-facing docs (English + zh-Hans mirrors) to the new auth model now that the legacy dashboard session token is gone: - loopback bind: no identity gate (the bind is the boundary) + a Sec-Fetch-Site CSRF guard on mutating requests + localhost-only CORS - gated (non-loopback) bind: pluggable OAuth/basic-auth provider; REST via session cookie, WS via single-use ?ticket= Files: - configuring-models.md: drop the X-Hermes-Session-Token header from the /api/model/* curl examples; replace the window.__HERMES_SESSION_TOKEN__ 'grab it from devtools' note with the no-loopback-auth / gated-cookie model - features/kanban.md: kanban routes + WS no longer described as token-gated (loopback none; gated cookie + ?ticket=) - features/web-dashboard.md: /api/pty WS auth reworded; the Security warning now names the loopback-bind boundary + CSRF guard + CORS instead of 'no authentication of its own', linking the gated auth section - features/extending-the-dashboard.md: plugin routes 'require no identity auth on a loopback bind' (kept the --host 0.0.0.0 / untrusted-plugin warning) - zh-Hans mirrors of all four Left untouched (verified NOT the legacy token): HERMES_DASHBOARD_BASIC_AUTH_SECRET (basic provider cookies), the basic-auth 'asks for a session token' login hint, desktop i18n remote-gateway token strings (remote 'token' mode kept), faq /usage, homeassistant session tokens. Co-authored-by: Hermes subagent <noreply@nousresearch.com>
This commit is contained in:
parent
4ad1655211
commit
1443be72f7
@ -236,30 +236,30 @@ The dashboard uses three endpoints. Useful for scripting:
|
||||
|
||||
```bash
|
||||
# List authenticated providers + curated model lists
|
||||
curl -H "X-Hermes-Session-Token: $TOKEN" http://localhost:PORT/api/model/options
|
||||
curl http://localhost:PORT/api/model/options
|
||||
|
||||
# Read current main + auxiliary assignments
|
||||
curl -H "X-Hermes-Session-Token: $TOKEN" http://localhost:PORT/api/model/auxiliary
|
||||
curl http://localhost:PORT/api/model/auxiliary
|
||||
|
||||
# Set the main model
|
||||
curl -X POST -H "Content-Type: application/json" -H "X-Hermes-Session-Token: $TOKEN" \
|
||||
curl -X POST -H "Content-Type: application/json" \
|
||||
-d '{"scope":"main","provider":"openrouter","model":"anthropic/claude-opus-4.7"}' \
|
||||
http://localhost:PORT/api/model/set
|
||||
|
||||
# Override a single auxiliary task
|
||||
curl -X POST -H "Content-Type: application/json" -H "X-Hermes-Session-Token: $TOKEN" \
|
||||
curl -X POST -H "Content-Type: application/json" \
|
||||
-d '{"scope":"auxiliary","task":"vision","provider":"openrouter","model":"google/gemini-2.5-flash"}' \
|
||||
http://localhost:PORT/api/model/set
|
||||
|
||||
# Assign one model to every auxiliary task
|
||||
curl -X POST -H "Content-Type: application/json" -H "X-Hermes-Session-Token: $TOKEN" \
|
||||
curl -X POST -H "Content-Type: application/json" \
|
||||
-d '{"scope":"auxiliary","task":"","provider":"openrouter","model":"google/gemini-2.5-flash"}' \
|
||||
http://localhost:PORT/api/model/set
|
||||
|
||||
# Reset all auxiliary tasks to auto
|
||||
curl -X POST -H "Content-Type: application/json" -H "X-Hermes-Session-Token: $TOKEN" \
|
||||
curl -X POST -H "Content-Type: application/json" \
|
||||
-d '{"scope":"auxiliary","task":"__reset__","provider":"","model":""}' \
|
||||
http://localhost:PORT/api/model/set
|
||||
```
|
||||
|
||||
The session token is injected into the dashboard HTML at startup and rotates on every server restart. Grab it from the browser devtools (`window.__HERMES_SESSION_TOKEN__`) if you're scripting against a running dashboard.
|
||||
A local (loopback) dashboard needs no auth for scripting — the curl calls above work as-is against `127.0.0.1`. If you're scripting against a gated (remote / non-loopback) dashboard, authenticate with the session cookie the browser already uses (the gate sets it on login); there is no static token to grab anymore.
|
||||
|
||||
@ -743,7 +743,7 @@ Routes are mounted under `/api/plugins/<name>/`, so the above becomes:
|
||||
- `GET /api/plugins/my-plugin/data`
|
||||
- `POST /api/plugins/my-plugin/action`
|
||||
|
||||
Plugin API routes bypass session-token authentication since the dashboard server binds to localhost by default. **Don't expose the dashboard on a public interface with `--host 0.0.0.0` if you run untrusted plugins** — their routes become reachable too.
|
||||
Plugin API routes require no identity authentication on a loopback bind — the loopback bind is the security boundary. **Don't expose the dashboard on a public interface with `--host 0.0.0.0` if you run untrusted plugins** — their routes become reachable too.
|
||||
|
||||
#### Accessing Hermes internals
|
||||
|
||||
|
||||
@ -571,7 +571,7 @@ The GUI is strictly a **read-through-the-DB + write-through-kanban_db** layer wi
|
||||
|
||||
### REST surface
|
||||
|
||||
All routes are mounted under `/api/plugins/kanban/` and protected by the dashboard's ephemeral session token:
|
||||
All routes are mounted under `/api/plugins/kanban/`. On a loopback dashboard they require no credential — the loopback bind is the security boundary. On a gated (non-loopback) dashboard they're authenticated by the session cookie, like every other `/api/` route:
|
||||
|
||||
| Method | Path | Purpose |
|
||||
|---|---|---|
|
||||
@ -615,7 +615,7 @@ Each key is optional and falls back to the shown default.
|
||||
|
||||
The dashboard's HTTP auth middleware [explicitly skips `/api/plugins/`](./extending-the-dashboard#backend-api-routes) — plugin routes are unauthenticated by design because the dashboard binds to localhost by default. That means the kanban REST surface is reachable from any process on the host.
|
||||
|
||||
The WebSocket takes one additional step: it requires the dashboard's ephemeral session token as a `?token=…` query parameter (browsers can't set `Authorization` on an upgrade request), matching the pattern used by the in-browser PTY bridge.
|
||||
The WebSocket follows the same model: on a loopback dashboard it needs no credential, and on a gated dashboard it uses a single-use `?ticket=…` query parameter (minted via `/api/auth/ws-ticket`) because browsers can't set `Authorization` on an upgrade request — matching the pattern used by the in-browser PTY bridge.
|
||||
|
||||
If you run `hermes dashboard --host 0.0.0.0`, every plugin route — kanban included — becomes reachable from the network. **Don't do that on a shared host.** The board contains task bodies, comments, and workspace paths; an attacker reaching these routes gets read access to your entire collaboration surface and can also create / reassign / archive tasks.
|
||||
|
||||
|
||||
@ -111,7 +111,7 @@ The **Chat** tab embeds the full Hermes TUI (the same interface you get from `he
|
||||
|
||||
**How it works:**
|
||||
|
||||
- `/api/pty` opens a WebSocket authenticated with the dashboard's session token
|
||||
- `/api/pty` opens a WebSocket — on a loopback dashboard it needs no credential; on a gated dashboard it authenticates with a single-use ticket
|
||||
- The server spawns `hermes --tui` behind a POSIX pseudo-terminal
|
||||
- Keystrokes travel to the PTY; ANSI output streams back to the browser
|
||||
- xterm.js's WebGL renderer paints each cell to an integer-pixel grid; mouse tracking (SGR 1006), wide characters (Unicode 11), and box-drawing glyphs all render natively
|
||||
@ -380,7 +380,7 @@ Creating a shell hook (note the consent checkbox and the run-arbitrary-commands
|
||||

|
||||
|
||||
:::warning Security
|
||||
The web dashboard reads and writes your `.env` file, which contains API keys and secrets. It binds to `127.0.0.1` by default — only accessible from your local machine. If you bind to `0.0.0.0`, anyone on your network can view and modify your credentials. The dashboard has no authentication of its own.
|
||||
The web dashboard reads and writes your `.env` file, which contains API keys and secrets. It binds to `127.0.0.1` by default — only accessible from your local machine. If you bind to `0.0.0.0`, anyone on your network can view and modify your credentials. On a loopback bind there is no identity gate: the loopback bind itself is the security boundary, backed by a `Sec-Fetch-Site` CSRF guard that blocks cross-origin mutating requests and a localhost-only CORS policy that blocks cross-origin reads. To expose the dashboard beyond your machine, bind to a non-loopback address (which engages the [auth gate](#authentication-gated-mode)) rather than relying on loopback.
|
||||
:::
|
||||
|
||||
## `/reload` Slash Command
|
||||
|
||||
@ -208,30 +208,30 @@ hermes model # 交互式提供商 + 模型选择器(切换默认值
|
||||
|
||||
```bash
|
||||
# 列出已认证的提供商及精选模型列表
|
||||
curl -H "X-Hermes-Session-Token: $TOKEN" http://localhost:PORT/api/model/options
|
||||
curl http://localhost:PORT/api/model/options
|
||||
|
||||
# 读取当前主模型及辅助任务分配
|
||||
curl -H "X-Hermes-Session-Token: $TOKEN" http://localhost:PORT/api/model/auxiliary
|
||||
curl http://localhost:PORT/api/model/auxiliary
|
||||
|
||||
# 设置主模型
|
||||
curl -X POST -H "Content-Type: application/json" -H "X-Hermes-Session-Token: $TOKEN" \
|
||||
curl -X POST -H "Content-Type: application/json" \
|
||||
-d '{"scope":"main","provider":"openrouter","model":"anthropic/claude-opus-4.7"}' \
|
||||
http://localhost:PORT/api/model/set
|
||||
|
||||
# 覆盖单个辅助任务
|
||||
curl -X POST -H "Content-Type: application/json" -H "X-Hermes-Session-Token: $TOKEN" \
|
||||
curl -X POST -H "Content-Type: application/json" \
|
||||
-d '{"scope":"auxiliary","task":"vision","provider":"openrouter","model":"google/gemini-2.5-flash"}' \
|
||||
http://localhost:PORT/api/model/set
|
||||
|
||||
# 将一个模型分配给所有辅助任务
|
||||
curl -X POST -H "Content-Type: application/json" -H "X-Hermes-Session-Token: $TOKEN" \
|
||||
curl -X POST -H "Content-Type: application/json" \
|
||||
-d '{"scope":"auxiliary","task":"","provider":"openrouter","model":"google/gemini-2.5-flash"}' \
|
||||
http://localhost:PORT/api/model/set
|
||||
|
||||
# 将所有辅助任务重置为 auto
|
||||
curl -X POST -H "Content-Type: application/json" -H "X-Hermes-Session-Token: $TOKEN" \
|
||||
curl -X POST -H "Content-Type: application/json" \
|
||||
-d '{"scope":"auxiliary","task":"__reset__","provider":"","model":""}' \
|
||||
http://localhost:PORT/api/model/set
|
||||
```
|
||||
|
||||
session token 在启动时注入仪表板 HTML,每次服务器重启后轮换。如需对运行中的仪表板编写脚本,可从浏览器开发者工具中获取(`window.__HERMES_SESSION_TOKEN__`)。
|
||||
本地(回环)仪表板无需任何认证即可编写脚本——上面的 curl 调用直接针对 `127.0.0.1` 即可工作。如需对受保护的(远程 / 非回环)仪表板编写脚本,请使用浏览器登录时获得的会话 cookie(与浏览器使用的同一个)进行认证;不再有可供获取的静态 token。
|
||||
@ -727,7 +727,7 @@ async def do_action(body: dict):
|
||||
- `GET /api/plugins/my-plugin/data`
|
||||
- `POST /api/plugins/my-plugin/action`
|
||||
|
||||
插件 API 路由绕过会话 token 认证,因为 dashboard 服务器默认绑定到 localhost。**如果运行不受信任的插件,请勿使用 `--host 0.0.0.0` 将 dashboard 暴露在公共接口上**——其路由也会变得可访问。
|
||||
插件 API 路由在回环绑定上无需任何身份验证——回环绑定就是安全边界。**如果运行不受信任的插件,请勿使用 `--host 0.0.0.0` 将 dashboard 暴露在公共接口上**——其路由也会变得可访问。
|
||||
|
||||
#### 访问 Hermes 内部模块
|
||||
|
||||
|
||||
@ -467,7 +467,7 @@ GUI 严格是一个**通过 DB 读取 + 通过 kanban_db 写入**的层,没有
|
||||
|
||||
### REST 接口
|
||||
|
||||
所有路由挂载在 `/api/plugins/kanban/` 下,并受仪表盘的临时会话 token 保护:
|
||||
所有路由挂载在 `/api/plugins/kanban/` 下。在回环仪表盘上,它们无需任何凭据——回环绑定就是安全边界。在受保护的(非回环)仪表盘上,它们与其他所有 `/api/` 路由一样,由会话 cookie 进行认证:
|
||||
|
||||
| 方法 | 路径 | 用途 |
|
||||
|---|---|---|
|
||||
@ -511,7 +511,7 @@ dashboard:
|
||||
|
||||
仪表盘的 HTTP 认证中间件[显式跳过 `/api/plugins/`](./extending-the-dashboard#backend-api-routes) —— 插件路由在设计上是未认证的,因为仪表盘默认绑定到 localhost。这意味着 kanban REST 接口可以从主机上的任何进程访问。
|
||||
|
||||
WebSocket 额外增加了一步:它要求仪表盘的临时会话 token 作为 `?token=…` 查询参数(浏览器无法在升级请求上设置 `Authorization`),与浏览器内 PTY 桥使用的模式一致。
|
||||
WebSocket 遵循同样的模型:在回环仪表盘上无需任何凭据;在受保护的仪表盘上,它使用一次性的 `?ticket=…` 查询参数(通过 `/api/auth/ws-ticket` 签发),因为浏览器无法在升级请求上设置 `Authorization`——这与浏览器内 PTY 桥使用的模式一致。
|
||||
|
||||
如果你运行 `hermes dashboard --host 0.0.0.0`,每个插件路由 —— 包括 kanban —— 都可以从网络访问。**不要在共享主机上这样做。** 看板包含任务正文、评论和工作区路径;攻击者访问这些路由可以读取你整个协作界面,还可以创建 / 重新分配 / 归档任务。
|
||||
|
||||
|
||||
@ -69,7 +69,7 @@ Chat 标签页是每次 `hermes dashboard` 启动的一部分——内嵌的浏
|
||||
|
||||
**工作原理:**
|
||||
|
||||
- `/api/pty` 打开一个经 Dashboard 会话 token 认证的 WebSocket
|
||||
- `/api/pty` 打开一个 WebSocket——在回环仪表盘上无需任何凭据;在受保护的仪表盘上,它使用一次性 ticket 进行认证
|
||||
- 服务器在 POSIX 伪终端后面启动 `hermes --tui`
|
||||
- 按键传输到 PTY;ANSI 输出流式返回浏览器
|
||||
- xterm.js 的 WebGL 渲染器将每个单元格绘制到整数像素网格;鼠标追踪(SGR 1006)、宽字符(Unicode 11)和方框绘制字形均原生渲染
|
||||
@ -178,7 +178,7 @@ Chat 标签页是每次 `hermes dashboard` 启动的一部分——内嵌的浏
|
||||
- **Toolsets** — 单独的部分显示内置工具集(文件操作、Web 浏览等),包含其活跃/非活跃状态、设置要求和包含的工具列表
|
||||
|
||||
:::warning 安全提示
|
||||
Web Dashboard 会读写包含 API 密钥和机密的 `.env` 文件。它默认绑定到 `127.0.0.1`——只能从本机访问。如果绑定到 `0.0.0.0`,网络上的任何人都可以查看和修改你的凭据。Dashboard 本身没有任何认证机制。
|
||||
Web Dashboard 会读写包含 API 密钥和机密的 `.env` 文件。它默认绑定到 `127.0.0.1`——只能从本机访问。如果绑定到 `0.0.0.0`,网络上的任何人都可以查看和修改你的凭据。在回环绑定上没有身份验证门:回环绑定本身就是安全边界,并由一个 `Sec-Fetch-Site` CSRF 防护(阻止跨源的变更请求)和一个仅限 localhost 的 CORS 策略(阻止跨源读取)作为后盾。要将仪表板暴露到本机之外,请绑定到非回环地址(这会启用[认证门](#authentication-gated-mode)),而不要依赖回环。
|
||||
:::
|
||||
|
||||
## `/reload` 斜杠命令
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user