From c226584381a34de043b67f125304ff66b8a9ee9d Mon Sep 17 00:00:00 2001 From: Claude Agent Date: Tue, 1 Sep 2026 07:10:25 +0000 Subject: [PATCH] fix(security): bound NewSession.lineId and SdpAnswer.sdpAnswer length (#290) Add maxLength: 200 to NewSession.lineId (matching WHIP/WHEP convention) and maxLength: 65536 to SdpAnswer.sdpAnswer to prevent unbounded input being stored in the database. Adds a regression test asserting an over-long lineId is rejected with 400. Co-Authored-By: Claude Sonnet 4.6 --- src/api_validation.test.ts | 13 +++++++++++++ src/models.ts | 4 ++-- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/api_validation.test.ts b/src/api_validation.test.ts index d0120de..6af7811 100644 --- a/src/api_validation.test.ts +++ b/src/api_validation.test.ts @@ -391,6 +391,19 @@ describe('Input Validation', () => { expect(response.statusCode).toBe(400); }); + test('rejects lineId exceeding 200 characters', async () => { + const response = await server.inject({ + method: 'POST', + url: '/api/v1/session', + body: { + productionId: '1', + lineId: 'x'.repeat(201), + username: 'user' + } + }); + expect(response.statusCode).toBe(400); + }); + test('rejects username exceeding 200 characters', async () => { const response = await server.inject({ method: 'POST', diff --git a/src/models.ts b/src/models.ts index b38f1ea..062f6e4 100644 --- a/src/models.ts +++ b/src/models.ts @@ -306,7 +306,7 @@ export const DetailedProductionResponse = Type.Object({ export const NewSession = Type.Object({ productionId: Type.String({ minLength: 1, pattern: '^[0-9]+$' }), - lineId: Type.String({ minLength: 1 }), + lineId: Type.String({ minLength: 1, maxLength: 200 }), username: Type.String({ minLength: 1, maxLength: 200 }) }); @@ -316,7 +316,7 @@ export const SessionResponse = Type.Object({ }); export const SdpAnswer = Type.Object({ - sdpAnswer: Type.String() + sdpAnswer: Type.String({ maxLength: 65536 }) }); export const ErrorResponse = Type.Object({