From 5aaf4a3b581716f6866acf88e51f2fe7f09cfbcd Mon Sep 17 00:00:00 2001 From: aiirvizionz Date: Fri, 10 Jul 2026 13:49:23 -0600 Subject: [PATCH] Handle invalid Telnyx webhook JSON --- src/app/api/webhooks/telnyx/sms/route.js | 10 +++- src/app/api/webhooks/telnyx/sms/route.test.js | 46 +++++++++++++++++++ 2 files changed, 54 insertions(+), 2 deletions(-) create mode 100644 src/app/api/webhooks/telnyx/sms/route.test.js diff --git a/src/app/api/webhooks/telnyx/sms/route.js b/src/app/api/webhooks/telnyx/sms/route.js index 7030113..dbf39f8 100644 --- a/src/app/api/webhooks/telnyx/sms/route.js +++ b/src/app/api/webhooks/telnyx/sms/route.js @@ -77,7 +77,13 @@ export async function POST(request) { return NextResponse.json({ error: 'Invalid signature' }, { status: 401 }); } - const body = JSON.parse(rawBody); + let body; + try { + body = JSON.parse(rawBody); + } catch (parseError) { + console.error('[TELNYX-WEBHOOK] Invalid JSON payload:', parseError.message); + return NextResponse.json({ error: 'Invalid JSON payload' }, { status: 400 }); + } // Log the incoming webhook for debugging console.log('[TELNYX-WEBHOOK] Received webhook:', { @@ -238,4 +244,4 @@ export async function GET() { service: 'telnyx-sms-webhook', timestamp: new Date().toISOString() }); -} \ No newline at end of file +} diff --git a/src/app/api/webhooks/telnyx/sms/route.test.js b/src/app/api/webhooks/telnyx/sms/route.test.js new file mode 100644 index 0000000..5d40b4c --- /dev/null +++ b/src/app/api/webhooks/telnyx/sms/route.test.js @@ -0,0 +1,46 @@ +import { beforeEach, describe, expect, it, vi } from 'vitest'; + +const mocks = vi.hoisted(() => ({ + createServiceRoleClient: vi.fn(), + createSMSWebhookEmailService: vi.fn() +})); + +vi.mock('@/lib/supabase/service-role.js', () => ({ + createServiceRoleClient: mocks.createServiceRoleClient +})); + +vi.mock('@/lib/services/mailgun-email-service.js', () => ({ + createSMSWebhookEmailService: mocks.createSMSWebhookEmailService +})); + +function webhookRequest(body) { + return new Request('https://example.com/api/webhooks/telnyx/sms', { + method: 'POST', + headers: { + 'telnyx-signature-ed25519': 'dev-signature', + 'telnyx-timestamp': '1720000000' + }, + body + }); +} + +describe('Telnyx SMS webhook', () => { + beforeEach(() => { + vi.resetModules(); + vi.clearAllMocks(); + delete process.env.TELNYX_PUBLIC_KEY; + process.env.NODE_ENV = 'development'; + }); + + it('returns 400 for malformed JSON after signature verification', async () => { + const { POST } = await import('./route.js'); + + const response = await POST(webhookRequest('{not-json')); + const body = await response.json(); + + expect(response.status).toBe(400); + expect(body.error).toBe('Invalid JSON payload'); + expect(mocks.createServiceRoleClient).not.toHaveBeenCalled(); + expect(mocks.createSMSWebhookEmailService).not.toHaveBeenCalled(); + }); +});