HKUDS/Vibe-Trading · critical · ValueError

host is 0.0.0.0 (all interfaces) but neither token nor token

Error message

host is 0.0.0.0 (all interfaces) but neither token nor token_issue_secret is set — set one to prevent unauthenticated access

What it means

A safety model validator that fires when the WebSocket server binds to all interfaces (host 0.0.0.0 or ::) with no authentication configured — neither a static token nor a token_issue_secret. An unauthenticated WS server on all interfaces is exposed to the network, so the config is rejected rather than silently started.

Source

Thrown at agent/src/channels/websocket.py:139

        if not value.startswith("/"):
            raise ValueError('token_issue_path must start with "/"')
        return _normalize_config_path(value)

    @model_validator(mode="after")
    def token_issue_path_differs_from_ws_path(self) -> Self:
        if not self.token_issue_path:
            return self
        if _normalize_config_path(self.token_issue_path) == _normalize_config_path(self.path):
            raise ValueError("token_issue_path must differ from path (the WebSocket upgrade path)")
        return self

    @model_validator(mode="after")
    def wildcard_host_requires_auth(self) -> Self:
        if self.host not in ("0.0.0.0", "::"):
            return self
        if self.token.strip() or self.token_issue_secret.strip():
            return self
        raise ValueError(
            "host is 0.0.0.0 (all interfaces) but neither token nor "
            "token_issue_secret is set — set one to prevent unauthenticated access"
        )


def publish_runtime_model_update(
    bus: MessageBus,
    model: str,
    model_preset: str | None,
) -> None:
    """Enqueue a runtime model snapshot for websocket subscribers (fan-out in-channel)."""
    bus.outbound.put_nowait(OutboundMessage(
        channel="websocket",
        chat_id="*",
        content="",
        metadata={
            "_runtime_model_updated": True,
            "model": model,

View on GitHub (pinned to 80ffdda44c)

Solutions

  1. Set a strong token (shared bearer for WS clients) or a token_issue_secret for the token-issuing endpoint
  2. If the server is fronted by an authenticating reverse proxy on localhost, bind host="127.0.0.1" instead of 0.0.0.0
  3. Verify the env vars feeding token/token_issue_secret are actually present in the container/service (docker inspect or printenv)

Example fix

# before
WebSocketChannelConfig(host="0.0.0.0", port=8765)
# after
import secrets
WebSocketChannelConfig(
    host="0.0.0.0", port=8765,
    token=secrets.token_urlsafe(32),
)
Defensive patterns

Strategy: validation

Validate before calling

def guard_wildcard(cfg: dict) -> dict:
    if cfg.get("host") in ("0.0.0.0", "::") and not (cfg.get("token", "").strip() or cfg.get("token_issue_secret", "").strip()):
        import secrets
        cfg["token"] = secrets.token_urlsafe(32)  # or fail loudly
    return cfg

Type guard

def is_safe_bind(host: str, token: str, issue_secret: str) -> bool:
    return host not in ("0.0.0.0", "::") or bool(token.strip() or issue_secret.strip())

Prevention

When it happens

Trigger: WebSocketConfig(host="0.0.0.0") (or "::") with both token and token_issue_secret empty/whitespace. Binding to 127.0.0.1 or localhost skips the check entirely.

Common situations: Running in Docker/Kubernetes where the service must listen on 0.0.0.0 but auth env vars weren't provided; local dev config promoted to production; token env var name typo leaving token empty; expecting auth to be handled by an external proxy and forgetting the library still requires a token.

Understand the failure class

Related errors


AI-assisted analysis of HKUDS/Vibe-Trading@80ffdda44c (2026-08-28). Data as JSON: /api/errors/6eb7924c74297dfb. Report an issue: GitHub.