Skip to content

Commit ecda7c2

Browse files
nikolovlazarclaude
andcommitted
fix(tunnel): handle malformed envelope JSON with 400 response
Wrap parseEnvelope in try-catch so malformed request bodies return a 400 Bad Request instead of throwing an unhandled error. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 105b75a commit ecda7c2

2 files changed

Lines changed: 19 additions & 1 deletion

File tree

packages/core/src/utils/tunnel.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,13 @@ export async function handleTunnelRequest(options: HandleTunnelRequestOptions):
2727

2828
const body = new Uint8Array(await request.arrayBuffer());
2929

30-
const [envelopeHeader] = parseEnvelope(body);
30+
let envelopeHeader;
31+
try {
32+
[envelopeHeader] = parseEnvelope(body);
33+
} catch {
34+
return new Response('Invalid envelope', { status: 400 });
35+
}
36+
3137
if (!envelopeHeader) {
3238
return new Response('Invalid envelope: missing header', { status: 400 });
3339
}

packages/core/test/lib/utils/tunnel.test.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,18 @@ describe('handleTunnelRequest', () => {
6767
expect(fetchMock).not.toHaveBeenCalled();
6868
});
6969

70+
it('returns 400 when the envelope body contains malformed JSON', async () => {
71+
const result = await handleTunnelRequest({
72+
request: new Request('http://localhost/tunnel', { method: 'POST', body: 'not valid envelope data{{{' }),
73+
allowedDsns: [TEST_DSN],
74+
});
75+
76+
expect(result).toBeInstanceOf(Response);
77+
expect(result.status).toBe(400);
78+
expect(await result.text()).toBe('Invalid envelope');
79+
expect(fetchMock).not.toHaveBeenCalled();
80+
});
81+
7082
it('returns 403 when the envelope DSN is not in allowedDsns', async () => {
7183
const result = await handleTunnelRequest({
7284
request: makeEnvelopeRequest({ dsn: 'https://other@example.com/9999' }),

0 commit comments

Comments
 (0)