diff --git a/webview/shared/src/chat/lib/messageHandler.test.ts b/webview/shared/src/chat/lib/messageHandler.test.ts index 4bc7fe9..90e4e99 100644 --- a/webview/shared/src/chat/lib/messageHandler.test.ts +++ b/webview/shared/src/chat/lib/messageHandler.test.ts @@ -73,6 +73,25 @@ describe('extractEventMessageId', () => { }); }); +describe('malformed stream events', () => { + it('ignores null, undefined, primitive, and array event payloads', () => { + let state = { ...initialState, currentSessionId: 'ses-malformed' } as AppState; + const dispatch = (action: Parameters[1]) => { + state = appReducer(state, action); + }; + const handler = createMessageHandler(dispatch, () => state); + + for (const event of [null, undefined, 'invalid', []]) { + handler({ + data: { type: 'streamEvent', sessionId: 'ses-malformed', event }, + } as MessageEvent); + } + + assert.equal(state.isProcessing, false); + assert.equal(state.streaming, null); + }); +}); + describe('normalizeMessage - responseType handling', () => { it('ignores undefined interactive events from an untrusted payload', () => { const result = normalizeMessage({ diff --git a/webview/shared/src/chat/lib/messageHandler.ts b/webview/shared/src/chat/lib/messageHandler.ts index 1c14aa2..999fabb 100644 --- a/webview/shared/src/chat/lib/messageHandler.ts +++ b/webview/shared/src/chat/lib/messageHandler.ts @@ -9251,6 +9251,8 @@ function handleStreamEvent( knownReasoningPartIDs?: Set, pendingRenderableTextPart?: { partID?: string; messageID?: string }, ): void { + if (!payload || typeof payload !== "object") return; + const dispatchProcessingTrue = () => { if (!shouldSuppressProcessingBootstrap) { dispatch({ type: "SET_IS_PROCESSING", payload: true }); @@ -14303,7 +14305,11 @@ export function createMessageHandler(dispatch: Dispatch, getState: () } case "streamEvent": { const stateBeforeStreamEvent = getState(); - const payload = asRecord(data.event) ?? data; + const payload = asRecord(data.event); + if (!payload || Array.isArray(payload)) { + logger.warn("Ignoring stream event with an invalid payload"); + break; + } const streamEventType = asString(payload.type) || "unknown"; const envelopeSessionId = asString(data.sessionId) ||