{"record":{"id":"6eb7924c74297dfb","repo":"HKUDS/Vibe-Trading","slug":"host-is-0-0-0-0-all-interfaces-but-neither-token","errorCode":null,"errorMessage":"host is 0.0.0.0 (all interfaces) but neither token nor token_issue_secret is set — set one to prevent unauthenticated access","messagePattern":"host is 0\\.0\\.0\\.0 \\(all interfaces\\) but neither token nor token_issue_secret is set — set one to prevent unauthenticated access","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"critical","filePath":"agent/src/channels/websocket.py","lineNumber":139,"sourceCode":"        if not value.startswith(\"/\"):\n            raise ValueError('token_issue_path must start with \"/\"')\n        return _normalize_config_path(value)\n\n    @model_validator(mode=\"after\")\n    def token_issue_path_differs_from_ws_path(self) -> Self:\n        if not self.token_issue_path:\n            return self\n        if _normalize_config_path(self.token_issue_path) == _normalize_config_path(self.path):\n            raise ValueError(\"token_issue_path must differ from path (the WebSocket upgrade path)\")\n        return self\n\n    @model_validator(mode=\"after\")\n    def wildcard_host_requires_auth(self) -> Self:\n        if self.host not in (\"0.0.0.0\", \"::\"):\n            return self\n        if self.token.strip() or self.token_issue_secret.strip():\n            return self\n        raise ValueError(\n            \"host is 0.0.0.0 (all interfaces) but neither token nor \"\n            \"token_issue_secret is set — set one to prevent unauthenticated access\"\n        )\n\n\ndef publish_runtime_model_update(\n    bus: MessageBus,\n    model: str,\n    model_preset: str | None,\n) -> None:\n    \"\"\"Enqueue a runtime model snapshot for websocket subscribers (fan-out in-channel).\"\"\"\n    bus.outbound.put_nowait(OutboundMessage(\n        channel=\"websocket\",\n        chat_id=\"*\",\n        content=\"\",\n        metadata={\n            \"_runtime_model_updated\": True,\n            \"model\": model,","sourceCodeStart":121,"sourceCodeEnd":157,"githubUrl":"https://github.com/HKUDS/Vibe-Trading/blob/80ffdda44c5c4db0dd84d70e051cca591cea67df/agent/src/channels/websocket.py#L121-L157","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Set a strong token (shared bearer for WS clients) or a token_issue_secret for the token-issuing endpoint","If the server is fronted by an authenticating reverse proxy on localhost, bind host=\"127.0.0.1\" instead of 0.0.0.0","Verify the env vars feeding token/token_issue_secret are actually present in the container/service (docker inspect or printenv)"],"exampleFix":"# before\nWebSocketChannelConfig(host=\"0.0.0.0\", port=8765)\n# after\nimport secrets\nWebSocketChannelConfig(\n    host=\"0.0.0.0\", port=8765,\n    token=secrets.token_urlsafe(32),\n)","handlingStrategy":"validation","validationCode":"def guard_wildcard(cfg: dict) -> dict:\n    if cfg.get(\"host\") in (\"0.0.0.0\", \"::\") and not (cfg.get(\"token\", \"\").strip() or cfg.get(\"token_issue_secret\", \"\").strip()):\n        import secrets\n        cfg[\"token\"] = secrets.token_urlsafe(32)  # or fail loudly\n    return cfg","typeGuard":"def is_safe_bind(host: str, token: str, issue_secret: str) -> bool:\n    return host not in (\"0.0.0.0\", \"::\") or bool(token.strip() or issue_secret.strip())","tryCatchPattern":null,"preventionTips":["Treat 0.0.0.0 binds as production exposure — always pair with a token","Bind 127.0.0.1 when behind an authenticating reverse proxy","Check required auth env vars in container entrypoint before start"],"tags":["websocket","security","authentication","config-validation"],"backgroundTag":"unauthenticated-server-bind","analyzedSha":"80ffdda44c5c4db0dd84d70e051cca591cea67df","analyzedAt":"2026-08-28T12:46:38.989Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}