All articles

Convex Auth: 5 Mistakes AI Tools Keep Making in Your Queries

Convex Auth: 5 Mistakes AI Tools Keep Making in Your Queries

Convex's reactive model makes authorization hide in plain sight. Cursor / Claude scaffold queries without auth checks, and the whole app leaks user data by default. Here are the five patterns to fix.

April 24, 2026VibeWShield Team1 min read

Convex is beautiful for vibe-coders — one prompt and you get a reactive backend. It also routinely ships with zero authorization, because the LLM doesn't know where to put the check.

The five patterns we find

1. Query ignores ctx.auth

export const getOrder = query({
  args: { id: v.id("orders") },
  handler: async (ctx, args) => ctx.db.get(args.id),   // public
});

Anyone with a Convex client can call this with any order ID. Fix:

handler: async (ctx, args) => {
  const user = await ctx.auth.getUserIdentity();
  if (!user) throw new Error("unauthenticated");
  const order = await ctx.db.get(args.id);
  if (!order || order.userId !== user.subject) return null;
  return order;
},

2. Mutations that trust the client for userId

export const createOrder = mutation({
  args: { userId: v.id("users"), total: v.number() },
  ...
});

Never accept userId from the client. Derive it from ctx.auth.getUserIdentity().

3. by_ indexes with no scoping

Convex encourages indexes like by_status. Great — except a client can query every status across every user. Always include userId in the index when data is user-scoped.

4. Public actions calling private mutations

Actions run with elevated privilege and skip per-query auth. If one of them calls a mutation that mutates user data, the action itself is the authorization boundary — test it directly.

5. File storage URLs leaking across tenants

Convex storage URLs are signed but long-lived. If you paste one into a shared document, it's a tokenless credential.

Scan for it

VibeWShield's Convex module (shipping Sprint C) enumerates your deployed queries and replays each with a second session. Until then, grep your repo for query({ and mutation({ — count them, then count how many touch ctx.auth. The delta is your exposure.

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