New endpoint with no visible auth check
A new endpoint with no visible auth, or a webhook that does not check the sender's signature.
Why it matters
When an agent is asked to add a feature, it builds the handler that makes the feature work: parse the input, touch the database, return a result. Who is allowed to call it is a separate concern, and unless the task mentions it, the agent often leaves it out. Webhooks get the same treatment: the route is wired, the body is parsed, and signature verification is left as a TODO.
An endpoint without auth is callable by anyone who finds the URL, as often as they like. If it reads data, that data is public. If it writes, deletes or triggers paid work, strangers can do that too. An unverified webhook lets anyone post a fake paid invoice or completed checkout and have your code act on it.
Example
+import { NextResponse } from "next/server";
+import { prisma } from "@/lib/db";
+
+export async function DELETE(req: Request) {
+ const { searchParams } = new URL(req.url);
+ const id = searchParams.get("id");
+ await prisma.invoice.delete({ where: { id: id! } });
+ return NextResponse.json({ ok: true });
+}
What it detects
- New route declarations in source files: app.get and router.post style calls, FastAPI and Flask decorators, NestJS @Get and @Post, Next.js exported GET and POST handlers, Go handler functions and Deno.serve.
- Reported when nothing in the file as it stands after the change mentions auth, a session, a JWT, Clerk, NextAuth, Passport, login_required, an API key, a bearer token, a rate limit or middleware.
- Webhook routes (a path containing "webhook") where the file shows no signature check such as constructEvent, createHmac, timingSafeEqual, Svix, or a stripe-signature or x-hub-signature header.
- Health, readiness, metrics, robots.txt, favicon and .well-known paths are skipped as public by design.
- It cannot see auth applied in global middleware, a route group or an API gateway, so treat a finding as a prompt to confirm.
What to do when it fires
Require an authenticated session at the top of the handler, then check that the caller owns the record it is about to read or change. Add a rate limit if the endpoint does anything expensive. If the route really is meant to be public, add a comment saying so.
For a webhook, verify the provider's signature against the raw request body before reading the payload (for Stripe, stripe.webhooks.constructEvent with the endpoint secret) and reject the request when verification fails.