fix(security): block untrusted browser access to api server (#2451)

Co-authored-by: ifrederico <fr@tecompanytea.com>
This commit is contained in:
Teknium 2026-03-22 04:08:48 -07:00 committed by GitHub
parent b81926def6
commit e109a8b502
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 196 additions and 33 deletions

View file

@ -18,6 +18,9 @@ Add to `~/.hermes/.env`:
```bash
API_SERVER_ENABLED=true
API_SERVER_KEY=change-me-local-dev
# Optional: only if a browser must call Hermes directly
# API_SERVER_CORS_ORIGINS=http://localhost:3000
```
### 2. Start the gateway
@ -39,6 +42,7 @@ Point any OpenAI-compatible client at `http://localhost:8642/v1`:
```bash
# Test with curl
curl http://localhost:8642/v1/chat/completions \
-H "Authorization: Bearer change-me-local-dev" \
-H "Content-Type: application/json" \
-d '{"model": "hermes-agent", "messages": [{"role": "user", "content": "Hello!"}]}'
```
@ -168,12 +172,12 @@ Bearer token auth via the `Authorization` header:
Authorization: Bearer ***
```
Configure the key via `API_SERVER_KEY` env var. If no key is set, all requests are allowed (for local-only use).
Configure the key via `API_SERVER_KEY` env var. If you need a browser to call Hermes directly, also set `API_SERVER_CORS_ORIGINS` to an explicit allowlist.
:::warning Security
The API server gives full access to hermes-agent's toolset, **including terminal commands**. If you change the bind address to `0.0.0.0` (network-accessible), **always set `API_SERVER_KEY`** — without it, anyone on your network can execute arbitrary commands on your machine.
The API server gives full access to hermes-agent's toolset, **including terminal commands**. If you change the bind address to `0.0.0.0` (network-accessible), **always set `API_SERVER_KEY`** and keep `API_SERVER_CORS_ORIGINS` narrow — without that, remote callers may be able to execute arbitrary commands on your machine.
The default bind address (`127.0.0.1`) is safe for local-only use.
The default bind address (`127.0.0.1`) is for local-only use. Browser access is disabled by default; enable it only for explicit trusted origins.
:::
## Configuration
@ -186,6 +190,7 @@ The default bind address (`127.0.0.1`) is safe for local-only use.
| `API_SERVER_PORT` | `8642` | HTTP server port |
| `API_SERVER_HOST` | `127.0.0.1` | Bind address (localhost only by default) |
| `API_SERVER_KEY` | _(none)_ | Bearer token for auth |
| `API_SERVER_CORS_ORIGINS` | _(none)_ | Comma-separated allowed browser origins |
### config.yaml
@ -196,7 +201,15 @@ The default bind address (`127.0.0.1`) is safe for local-only use.
## CORS
The API server includes CORS headers on all responses (`Access-Control-Allow-Origin: *`), so browser-based frontends can connect directly.
The API server does **not** enable browser CORS by default.
For direct browser access, set an explicit allowlist:
```bash
API_SERVER_CORS_ORIGINS=http://localhost:3000,http://127.0.0.1:3000
```
Most documented frontends such as Open WebUI connect server-to-server and do not need CORS at all.
## Compatible Frontends

View file

@ -20,6 +20,8 @@ flowchart LR
Open WebUI connects to Hermes Agent's API server just like it would connect to OpenAI. Your agent handles the requests with its full toolset — terminal, file operations, web search, memory, skills — and returns the final response.
Open WebUI talks to Hermes server-to-server, so you do not need `API_SERVER_CORS_ORIGINS` for this integration.
## Quick Setup
### 1. Enable the API server
@ -28,8 +30,7 @@ Add to `~/.hermes/.env`:
```bash
API_SERVER_ENABLED=true
# Optional: set a key for auth (recommended if accessible beyond localhost)
# API_SERVER_KEY=your-secret-key
API_SERVER_KEY=your-secret-key
```
### 2. Start Hermes Agent gateway
@ -49,7 +50,7 @@ You should see:
```bash
docker run -d -p 3000:8080 \
-e OPENAI_API_BASE_URL=http://host.docker.internal:8642/v1 \
-e OPENAI_API_KEY=not-needed \
-e OPENAI_API_KEY=your-secret-key \
--add-host=host.docker.internal:host-gateway \
-v open-webui:/app/backend/data \
--name open-webui \
@ -57,12 +58,6 @@ docker run -d -p 3000:8080 \
ghcr.io/open-webui/open-webui:main
```
If you set an `API_SERVER_KEY`, use it instead of `not-needed`:
```bash
-e OPENAI_API_KEY=your-secret-key
```
### 4. Open the UI
Go to **http://localhost:3000**. Create your admin account (the first user becomes admin). You should see **hermes-agent** in the model dropdown. Start chatting!
@ -81,7 +76,7 @@ services:
- open-webui:/app/backend/data
environment:
- OPENAI_API_BASE_URL=http://host.docker.internal:8642/v1
- OPENAI_API_KEY=not-needed
- OPENAI_API_KEY=your-secret-key
extra_hosts:
- "host.docker.internal:host-gateway"
restart: always
@ -167,7 +162,7 @@ Your agent has access to all the same tools and capabilities as when using the C
| `API_SERVER_ENABLED` | `false` | Enable the API server |
| `API_SERVER_PORT` | `8642` | HTTP server port |
| `API_SERVER_HOST` | `127.0.0.1` | Bind address |
| `API_SERVER_KEY` | _(none)_ | Bearer token for auth. No key = allow all. |
| `API_SERVER_KEY` | _(required)_ | Bearer token for auth. Match `OPENAI_API_KEY`. |
### Open WebUI
@ -195,7 +190,7 @@ Hermes Agent may be executing multiple tool calls (reading files, running comman
### "Invalid API key" errors
Make sure your `OPENAI_API_KEY` in Open WebUI matches the `API_SERVER_KEY` in Hermes Agent. If no key is configured on the Hermes side, any non-empty value works.
Make sure your `OPENAI_API_KEY` in Open WebUI matches the `API_SERVER_KEY` in Hermes Agent.
## Linux Docker (no Docker Desktop)