🪻 distributed transcription service thistle.dunkirk.sh

chore: don't leak webhook errors

dunkirk.sh d024a754 3756b706

verified
Changed files
+20 -15
src
+20 -15
src/index.ts
···
},
"/api/webhooks/polar": {
POST: async (req) => {
-
try {
-
const { validateEvent } = await import("@polar-sh/sdk/webhooks");
+
const { validateEvent } = await import("@polar-sh/sdk/webhooks");
-
// Get raw body as string
-
const rawBody = await req.text();
-
const headers = Object.fromEntries(req.headers.entries());
+
// Get raw body as string
+
const rawBody = await req.text();
+
const headers = Object.fromEntries(req.headers.entries());
-
// Validate webhook signature (validated at startup)
-
const webhookSecret = process.env.POLAR_WEBHOOK_SECRET as string;
-
const event = validateEvent(rawBody, headers, webhookSecret);
+
// Validate webhook signature (validated at startup)
+
const webhookSecret = process.env.POLAR_WEBHOOK_SECRET as string;
+
let event: ReturnType<typeof validateEvent>;
+
try {
+
event = validateEvent(rawBody, headers, webhookSecret);
+
} catch (error) {
+
// Validation failed - log but return generic response
+
console.error("[Webhook] Signature validation failed:", error);
+
return Response.json({ error: "Invalid webhook" }, { status: 400 });
+
}
-
console.log(`[Webhook] Received event: ${event.type}`);
+
console.log(`[Webhook] Received event: ${event.type}`);
-
// Handle different event types
+
// Handle different event types
+
try {
switch (event.type) {
case "subscription.updated": {
const { id, status, customerId, metadata } = event.data;
···
return Response.json({ received: true });
} catch (error) {
-
console.error("[Webhook] Error processing webhook:", error);
-
return Response.json(
-
{ error: "Webhook processing failed" },
-
{ status: 400 },
-
);
+
// Processing failed - log with detail but return generic response
+
console.error("[Webhook] Event processing failed:", error);
+
return Response.json({ error: "Invalid webhook" }, { status: 400 });
},
},