Inngest Webhook Auth: When `event.key` Isn't Enough

Inngest signed webhooks are great — if you verify them. Vibe-coded handlers often trust the `event.key` field without checking the signature, and the whole workflow becomes callable by anyone.
Inngest gives you a reliable event/function model with automatic retries. It also requires you to verify the X-Inngest-Signature header on incoming webhook requests, and the AI scaffold routinely skips that step.
Vulnerable pattern
export const POST = async (req: Request) => {
const body = await req.json();
if (body.event.key !== "user/signup") return;
await grantWelcomeBonus(body.event.data.userId);
return Response.json({ ok: true });
};An attacker pings this with {"event": {"key": "user/signup", "data": {"userId": "<any>"}}} and every user becomes "welcome bonus" forever.
Correct pattern
Use the Inngest SDK handler:
import { serve } from "inngest/next";
import { inngest } from "@/inngest/client";
export const { GET, POST, PUT } = serve({
client: inngest,
functions: [welcomeBonus, /*...*/],
});The SDK verifies the signature for you. If you hand-write the handler, verify:
import crypto from "crypto";
const sig = req.headers.get("x-inngest-signature");
const body = await req.text();
const expected = crypto
.createHmac("sha256", process.env.INNGEST_SIGNING_KEY!)
.update(body)
.digest("hex");
if (!crypto.timingSafeEqual(Buffer.from(sig ?? ""), Buffer.from(expected))) {
return new Response("bad signature", { status: 401 });
}Bonus: idempotency
Even with signatures, retries happen. Always key your side effects (like granting a bonus) by event.id and store a processed-events log with a unique index. Two retries = one bonus.
Free security scan
Test your app for these vulnerabilities
VibeWShield automatically scans for everything covered in this article and more — 18 security checks in under 3 minutes.
Scan your app free