Fix remote-stack log streaming: URL-encode agent token in WS proxy (0.13.2)

The agent-logs WebSocket proxy injected the agent token raw into the upstream
query string (?token=<token>). Tokens containing base64/url-special characters
(+, /, =) were then mangled by the query parser on the agent side (e.g. "+"
decoded to a space), so the agent rejected the stream with close code 4401 even
though the same token works for the HTTP API (where it travels in the
Authorization header). URL-encode the token with urllib.parse.quote so it
round-trips intact.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
menzelj
2026-06-08 11:21:28 +00:00
co-authored by Claude Opus 4.8
parent 5ebd615651
commit 4bc0fb8901
4 changed files with 7 additions and 4 deletions
+1 -1
View File
@@ -40,7 +40,7 @@ from services import backup_service, compose_service
logger = logging.getLogger("stackpilot.agent")
AGENT_VERSION = "0.13.1"
AGENT_VERSION = "0.13.2"
# --------------------------------------------------------------------------- #
+1 -1
View File
@@ -55,7 +55,7 @@ async def lifespan(app: FastAPI):
schedule_task.cancel()
app = FastAPI(title="StackPilot", version="0.13.1", lifespan=lifespan)
app = FastAPI(title="StackPilot", version="0.13.2", lifespan=lifespan)
app.add_middleware(
CORSMiddleware,
+4 -1
View File
@@ -4,6 +4,7 @@ from __future__ import annotations
import asyncio
import json
import logging
import urllib.parse
import contextlib
@@ -114,7 +115,9 @@ async def ws_agent_logs(
ws_url = ("wss://" + base[8:] if base.startswith("https://")
else "ws://" + base[7:] if base.startswith("http://")
else "ws://" + base)
ws_url += f"/agent/ws/logs/{stack_id}?token={agent.token}"
# URL-encode the token: agent tokens may contain base64 chars (+ / =) that
# would otherwise be mangled in the query string and rejected as 4401.
ws_url += f"/agent/ws/logs/{stack_id}?token={urllib.parse.quote(agent.token, safe='')}"
async def _err(detail: str) -> None:
with contextlib.suppress(Exception):
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "stackpilot-frontend",
"private": true,
"version": "0.13.1",
"version": "0.13.2",
"type": "module",
"scripts": {
"dev": "vite",