Add session-based message filtering to prevent cross-session bleedthrough

- Filter chat events by sessionKey before forwarding to mobile clients
- Only forward messages matching the user's expected session (agent:main:{userId})
- Prevents desktop TUI messages from appearing on mobile devices
- Maintains backwards compatibility for main session messages
This commit is contained in:
2026-02-11 07:59:54 -08:00
parent 5401199162
commit 2e111d601c

View File

@@ -771,18 +771,33 @@ wss.on('connection', async (clientWs, req) => {
} }
}); });
// Proxy: OpenClaw → Client (inject user preferences into connect response) // Proxy: OpenClaw → Client (inject user preferences into connect response + filter by session)
openclawWs.on('message', (data) => { openclawWs.on('message', (data) => {
const message = data.toString('utf8'); const message = data.toString('utf8');
console.log(`[proxy] OpenClaw → Client: ${message.substring(0, 100)}...`); console.log(`[proxy] OpenClaw → Client: ${message.substring(0, 100)}...`);
console.log(`[proxy] Client WebSocket state: ${clientWs.readyState} (1=OPEN)`); console.log(`[proxy] Client WebSocket state: ${clientWs.readyState} (1=OPEN)`);
let messageToSend = data; let messageToSend = data;
let shouldForward = true;
// Try to inject user preferences into connect response // Try to filter and modify messages
try { try {
const parsed = JSON.parse(message); const parsed = JSON.parse(message);
// Filter chat events by sessionKey - only forward if it's for this user's session
if (parsed.type === 'event' && parsed.event === 'chat') {
const payloadSessionKey = parsed.payload?.sessionKey;
const expectedSessionKey = `agent:main:${clientUserId}`;
// Only forward if sessionKey matches user's session (or is main/unspecified for backwards compat)
if (payloadSessionKey && payloadSessionKey !== 'agent:main:main' && payloadSessionKey !== expectedSessionKey) {
console.log(`[proxy] Filtering out chat event: sessionKey=${payloadSessionKey}, expected=${expectedSessionKey}`);
shouldForward = false;
} else {
console.log(`[proxy] Forwarding chat event: sessionKey=${payloadSessionKey || 'main'} for user ${clientUserId}`);
}
}
// If this is a connect response, inject user preferences // If this is a connect response, inject user preferences
if (parsed.type === 'res' && parsed.ok && parsed.id && parsed.id.startsWith('connect-')) { if (parsed.type === 'res' && parsed.ok && parsed.id && parsed.id.startsWith('connect-')) {
console.log(`[prefs] Injecting user preferences into connect response for ${clientUserId}`); console.log(`[prefs] Injecting user preferences into connect response for ${clientUserId}`);
@@ -841,13 +856,16 @@ This file is dynamically updated on each user connection by alfred-proxy.
// Not JSON or couldn't parse, send as-is // Not JSON or couldn't parse, send as-is
} }
if (clientWs.readyState === WebSocket.OPEN) { // Only forward if not filtered
if (shouldForward && clientWs.readyState === WebSocket.OPEN) {
try { try {
clientWs.send(messageToSend); clientWs.send(messageToSend);
console.log(`[proxy] Message sent to client successfully`); console.log(`[proxy] Message sent to client successfully`);
} catch (err) { } catch (err) {
console.error(`[proxy] Failed to send to client:`, err.message); console.error(`[proxy] Failed to send to client:`, err.message);
} }
} else if (!shouldForward) {
console.log(`[proxy] Message filtered, not forwarding to client`);
} else { } else {
console.warn(`[proxy] Client WebSocket not open, cannot send (state=${clientWs.readyState})`); console.warn(`[proxy] Client WebSocket not open, cannot send (state=${clientWs.readyState})`);
} }