diff --git a/src/app/api/chat/messages/[id]/route.js b/src/app/api/chat/messages/[id]/route.js index 619c2ba1..b7d3a4d4 100644 --- a/src/app/api/chat/messages/[id]/route.js +++ b/src/app/api/chat/messages/[id]/route.js @@ -105,6 +105,11 @@ export async function GET(request, { params } = {}) { // Handle encrypted content - could be base64 string or serialized Buffer object const rawContent = message.message_recipients[0].encrypted_content; + if (typeof rawContent !== 'string') { + console.error('[API GET] Invalid encrypted content type for message:', message.id, typeof rawContent); + return NextResponse.json({ error: 'Invalid encrypted content' }, { status: 500 }); + } + try { // Check if it's a serialized Buffer object (JSON string containing {"type":"Buffer","data":[...]}) if (typeof rawContent === 'string' && rawContent.includes('"type":"Buffer"')) { diff --git a/src/app/api/chat/messages/[id]/route.test.js b/src/app/api/chat/messages/[id]/route.test.js index afb5878f..262ac919 100644 --- a/src/app/api/chat/messages/[id]/route.test.js +++ b/src/app/api/chat/messages/[id]/route.test.js @@ -49,6 +49,26 @@ function createMessagesQuery() { return query; } +function createMessagesQueryWithEncryptedContent(encryptedContent) { + const query = { + select: vi.fn(() => query), + eq: mocks.messageEq, + single: vi.fn().mockResolvedValue({ + data: { + id: 'message-1', + message_recipients: [ + { + encrypted_content: encryptedContent + } + ] + }, + error: null + }) + }; + mocks.messageEq.mockReturnValue(query); + return query; +} + describe('GET /api/chat/messages/[id]', () => { beforeEach(() => { vi.resetModules(); @@ -93,4 +113,25 @@ describe('GET /api/chat/messages/[id]', () => { expect(body).toEqual({ error: 'Message ID is required' }); expect(mocks.authGetUser).not.toHaveBeenCalled(); }); + + it('returns a controlled error for non-string encrypted content', async () => { + mocks.from.mockImplementation((table) => { + if (table === 'users') return createUsersQuery(); + if (table === 'messages') return createMessagesQueryWithEncryptedContent({ type: 'Buffer', data: [] }); + throw new Error(`Unexpected table: ${table}`); + }); + + const { GET } = await import('./route.js'); + const response = await GET( + new Request('https://qrypt.chat/api/chat/messages/message-1', { + headers: { cookie: 'sb-access-token=valid-token' } + }), + { params: Promise.resolve({ id: 'message-1' }) } + ); + const body = await response.json(); + + expect(response.status).toBe(500); + expect(body).toEqual({ error: 'Invalid encrypted content' }); + expect(mocks.messageEq).toHaveBeenCalledWith('id', 'message-1'); + }); });