From 14fb6d6cd4c85078a986c7645ea1dd7fa39d6928 Mon Sep 17 00:00:00 2001 From: siddseethepalli Date: Tue, 17 Feb 2026 04:45:35 +0000 Subject: [PATCH] fix: filter unauthenticated sockets from broadcast and handle missing token for SSH-forwarded sockets - broadcast() now iterates over authenticatedSockets instead of connectedSockets, preventing unauthenticated connections from receiving broadcast messages during the 5-second auth window. - CLI connect() now gracefully handles missing session token when VELLUM_DAEMON_SOCKET is set (SSH-forwarded socket), instead of hard-failing before the IPC exchange. Addresses feedback from #3375. Co-Authored-By: Claude Opus 4.6 --- assistant/src/cli.ts | 10 ++++++++++ assistant/src/daemon/server.ts | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/assistant/src/cli.ts b/assistant/src/cli.ts index 67ad5efdb77..9c045cc139a 100644 --- a/assistant/src/cli.ts +++ b/assistant/src/cli.ts @@ -3,6 +3,7 @@ import * as readline from 'node:readline'; import { readFileSync, appendFileSync, mkdirSync } from 'node:fs'; import { dirname } from 'node:path'; import { getSocketPath, getHistoryPath, readSessionToken } from './util/platform.js'; +import { hasSocketOverride } from './daemon/connection-policy.js'; import { serialize, createMessageParser, @@ -666,6 +667,15 @@ export async function startCli(): Promise { // accept any other messages. const token = readSessionToken(); if (!token) { + if (hasSocketOverride()) { + // SSH-forwarded socket: the token file lives on the remote + // host, not locally. Connect without auth and let the server + // decide whether to accept the unauthenticated connection. + authenticated = true; + startHeartbeat(); + resolve(); + return; + } reject(new Error('Session token not found — is the daemon running?')); newSocket.destroy(); return; diff --git a/assistant/src/daemon/server.ts b/assistant/src/daemon/server.ts index ebbab442076..b39afcd9a82 100644 --- a/assistant/src/daemon/server.ts +++ b/assistant/src/daemon/server.ts @@ -609,7 +609,7 @@ export class DaemonServer { } broadcast(msg: ServerMessage, excludeSocket?: net.Socket): void { - for (const socket of this.connectedSockets) { + for (const socket of this.authenticatedSockets) { if (socket === excludeSocket) continue; this.send(socket, msg); }