Skip to content

Commit 9e23674

Browse files
committed
🔒 security(api): remove client ID and IP from SSE connect/disconnect log lines
- SSE lifecycle logs no longer leak raw client identifiers or source IPs into the system log - Per-IP connection limit warnings no longer echo the rate-limited address
1 parent 0173d7e commit 9e23674

File tree

2 files changed

+28
-5
lines changed

2 files changed

+28
-5
lines changed

‎app/api/sse.test.ts‎

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,29 @@ describe('SSE Router', () => {
348348
expect(sseRouter._clients.size).toBe(1);
349349
});
350350

351+
test('should log connection lifecycle without raw client identifiers', () => {
352+
const handler = getHandler();
353+
const req = createSSERequest('203.0.113.10');
354+
const res = createSSEResponse();
355+
356+
handler(req, res);
357+
const connectedPayload = parseSseEventPayload(res, 'dd:connected');
358+
359+
expect(mockLoggerDebug).toHaveBeenCalledWith('SSE client connected (1 total)');
360+
expect(mockLoggerDebug).not.toHaveBeenCalledWith(
361+
expect.stringContaining(connectedPayload.clientId),
362+
);
363+
expect(mockLoggerDebug).not.toHaveBeenCalledWith(expect.stringContaining('203.0.113.10'));
364+
365+
req._listeners.close();
366+
367+
expect(mockLoggerDebug).toHaveBeenCalledWith('SSE client disconnected (0 total)');
368+
expect(mockLoggerDebug).not.toHaveBeenCalledWith(
369+
expect.stringContaining(connectedPayload.clientId),
370+
);
371+
expect(mockLoggerDebug).not.toHaveBeenCalledWith(expect.stringContaining('203.0.113.10'));
372+
});
373+
351374
test('should remove client on connection close', () => {
352375
const handler = getHandler();
353376
const req = createSSERequest();
@@ -608,6 +631,8 @@ describe('SSE Router', () => {
608631

609632
expect(rejectedRes.status).toHaveBeenCalledWith(429);
610633
expect(rejectedRes.json).toHaveBeenCalledWith({ error: 'Too many SSE connections' });
634+
expect(mockLoggerWarn).toHaveBeenCalledWith('SSE per-IP connection limit reached (10)');
635+
expect(mockLoggerWarn).not.toHaveBeenCalledWith(expect.stringContaining(ip));
611636
});
612637

613638
test('should allow connections from different IPs independently', () => {

‎app/api/sse.ts‎

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ function eventsHandler(req: Request, res: Response): void {
150150
const currentSessionCount = connectionsPerSession.get(sessionKey) ?? 0;
151151

152152
if (currentIpCount >= MAX_CONNECTIONS_PER_IP) {
153-
logger.warn(`SSE connection limit reached for ${ip} (${currentIpCount})`);
153+
logger.warn(`SSE per-IP connection limit reached (${currentIpCount})`);
154154
sendErrorResponse(res, 429, 'Too many SSE connections');
155155
return;
156156
}
@@ -194,7 +194,7 @@ function eventsHandler(req: Request, res: Response): void {
194194
client.flush?.();
195195

196196
clients.add(client);
197-
logger.debug(`SSE client connected: ${activeClient.clientId} from ${ip} (${clients.size} total)`);
197+
logger.debug(`SSE client connected (${clients.size} total)`);
198198
startSharedHeartbeatIntervalIfNeeded();
199199

200200
let disconnected = false;
@@ -222,9 +222,7 @@ function eventsHandler(req: Request, res: Response): void {
222222
} else {
223223
connectionsPerSession.set(sessionKey, sessionCount - 1);
224224
}
225-
logger.debug(
226-
`SSE client disconnected: ${activeClient.clientId} from ${ip} (${clients.size} total)`,
227-
);
225+
logger.debug(`SSE client disconnected (${clients.size} total)`);
228226
};
229227

230228
req.on('close', cleanup);

0 commit comments

Comments
 (0)