Skip to main content Skills Marktplatz Entdecken und erkunden Sie KI-Skills, die von der Community erstellt wurden.
Mit Codex oder Claude installieren Kopieren Sie diesen Prompt, fügen Sie ihn in Codex, Claude oder einen anderen Assistant ein und lassen Sie die Skill-Seite prüfen und installieren.
Prompt kopierenPrompt-Details anzeigen Ein direkter Befehl überspringt den Prüf-Prompt. Prüfen Sie die Quelle, bevor Sie ihn ausführen.
npx skills add https://github.com/ForceInjection/domain-driven-design-skills --skill security-convexDer Befehl bleibt in einer Zeile. Scrollen Sie horizontal, um ihn vor dem Kopieren vollständig zu prüfen.
Sie bevorzugen eine lokale Kopie? Laden Sie die Dateien herunter, die SkillsMP derzeit vorliegen.
ZIP herunterladen Herunterladen... Mehr aus diesem Repository
Conduct deep academic research for philosophy, neuroscience, cognitive science, and theoretical computer science (computability, complexity, AI theory, logic). Use when user asks to: research academic topics, find scholarly papers, conduct literature reviews, analyze citations, synthesize research findings, explore philosophical arguments, investigate consciousness/cognition, study computability/decidability/Turing machines, or analyze academic debates. Triggers on: 'research papers', 'literature review', 'academic sources', 'scholarly articles', 'philosophy of mind', 'computability theory', 'neuroscience studies', 'find papers on', 'what does the research say'.
Verwandte Berufe SOC
Basierend auf der SOC-Berufsklassifikation
name security-convex description Convex security audit patterns. Load when reviewing Convex apps (convex/ directory present). Covers query/mutation auth, row-level security, public vs authenticated functions, validators, and Convex-specific issues.
Security audit patterns for Convex applications covering authentication, authorization, input validation, and Convex-specific vulnerabilities.
The #1 Vibecoding Mistake: Unauthenticated Functions
Convex functions are public by default. Every query and mutation is callable from any client unless you add auth checks.
export const listUsers = query ({
handler : async (ctx) => {
return await ctx.db .query ("users" ).collect ();
},
});
export const deleteNote = mutation ({
args : { noteId : v.id ("notes" ) },
handler : async (ctx, args) => {
await ctx.db .delete (args.noteId );
},
});
listUsers = ({
: (ctx) => {
userId = (ctx);
(!userId) ( );
ctx. . ( ). ();
},
});
export
const
query
handler
async
const
await
getAuthUserId
if
throw
new
Error
"Unauthenticated"
return
await
db
query
"users"
collect
Authentication Checks
Using Convex Auth import { getAuthUserId } from "@convex-dev/auth/server" ;
export const getMyProfile = query ({
handler : async (ctx) => {
return await ctx.db .query ("users" ).first ();
},
});
export const getMyProfile = query ({
handler : async (ctx) => {
const userId = await getAuthUserId (ctx);
if (!userId) throw new Error ("Unauthenticated" );
return await ctx.db .get (userId);
},
});
Using Third-Party Auth (Clerk, Auth0)
export const sensitiveData = query ({
handler : async (ctx) => {
const identity = await ctx.auth .getUserIdentity ();
return await ctx.db .query ("secrets" ).collect ();
},
});
export const sensitiveData = query ({
handler : async (ctx) => {
const identity = await ctx.auth .getUserIdentity ();
if (!identity) throw new Error ("Unauthenticated" );
return await ctx.db .query ("secrets" )
.filter (q => q.eq (q.field ("userId" ), identity.subject ))
.collect ();
},
});
Authorization: The IDOR Problem Authentication (who you are) ≠ Authorization (what you can access).
export const getNote = query ({
args : { noteId : v.id ("notes" ) },
handler : async (ctx, args) => {
const userId = await getAuthUserId (ctx);
if (!userId) throw new Error ("Unauthenticated" );
return await ctx.db .get (args.noteId );
},
});
export const getNote = query ({
args : { noteId : v.id ("notes" ) },
handler : async (ctx, args) => {
const userId = await getAuthUserId (ctx);
if (!userId) throw new Error ("Unauthenticated" );
const note = await ctx.db .get (args.noteId );
if (!note || note.userId !== userId) {
throw new Error ("Not found" );
}
return note;
},
});
Team/Org Membership Checks
export const getTeamData = query ({
args : { teamId : v.id ("teams" ) },
handler : async (ctx, args) => {
const userId = await getAuthUserId (ctx);
if (!userId) throw new Error ("Unauthenticated" );
return await ctx.db .query ("projects" )
.filter (q => q.eq (q.field ("teamId" ), args.teamId ))
.collect ();
},
});
export const getTeamData = query ({
args : { teamId : v.id ("teams" ) },
handler : async (ctx, args) => {
const userId = await getAuthUserId (ctx);
if (!userId) throw new Error ("Unauthenticated" );
const membership = await ctx.db .query ("teamMembers" )
.withIndex ("by_team_user" , q =>
q.eq ("teamId" , args.teamId ).eq ("userId" , userId)
).first ();
if (!membership) throw new Error ("Not a team member" );
return await ctx.db .query ("projects" )
.filter (q => q.eq (q.field ("teamId" ), args.teamId ))
.collect ();
},
});
Custom Functions Pattern (Recommended) Use convex-helpers to enforce auth by default:
import { customQuery, customMutation } from "convex-helpers/server/customFunctions" ;
import { getAuthUserId } from "@convex-dev/auth/server" ;
export const userQuery = customQuery (query, {
args : {},
input : async (ctx) => {
const userId = await getAuthUserId (ctx);
if (!userId) throw new Error ("Unauthenticated" );
const user = await ctx.db .get (userId);
if (!user) throw new Error ("User not found" );
return { ctx : { user }, args : {} };
},
});
export const getMyNotes = userQuery ({
handler : async (ctx) => {
return await ctx.db .query ("notes" )
.filter (q => q.eq (q.field ("userId" ), ctx.user ._id ))
.collect ();
},
});
Audit: Check if custom functions are used consistently. Search for raw query( and mutation( usage.
Input Validation
Missing Validators
export const createNote = mutation ({
handler : async (ctx, args) => {
await ctx.db .insert ("notes" , args);
},
});
export const createNote = mutation ({
args : {
title : v.string (),
content : v.string (),
isPublic : v.optional (v.boolean ()),
},
handler : async (ctx, args) => {
const userId = await getAuthUserId (ctx);
if (!userId) throw new Error ("Unauthenticated" );
await ctx.db .insert ("notes" , {
...args,
userId,
});
},
});
Trusting Client-Provided IDs for Ownership
export const createNote = mutation ({
args : {
title : v.string (),
userId : v.id ("users" ),
},
handler : async (ctx, args) => {
await ctx.db .insert ("notes" , args);
},
});
export const createNote = mutation ({
args : { title : v.string () },
handler : async (ctx, args) => {
const userId = await getAuthUserId (ctx);
if (!userId) throw new Error ("Unauthenticated" );
await ctx.db .insert ("notes" , {
title : args.title ,
userId,
});
},
});
Internal Functions
export const processPayment = mutation ({
args : { amount : v.number () },
handler : async (ctx, args) => {
await chargeCard (args.amount );
},
});
export const processPayment = internalMutation ({
args : { userId : v.id ("users" ), amount : v.number () },
handler : async (ctx, args) => {
await chargeCard (args.amount );
},
});
export const purchaseItem = mutation ({
args : { itemId : v.id ("items" ) },
handler : async (ctx, args) => {
const userId = await getAuthUserId (ctx);
if (!userId) throw new Error ("Unauthenticated" );
const item = await ctx.db .get (args.itemId );
await ctx.runMutation (internal.payments .processPayment , {
userId,
amount : item.price ,
});
},
});
HTTP Actions
export const webhook = httpAction (async (ctx, request) => {
const body = await request.json ();
await ctx.runMutation (api.data .processWebhook , body);
return new Response ("OK" );
});
export const webhook = httpAction (async (ctx, request) => {
const signature = request.headers .get ("x-webhook-signature" );
const body = await request.text ();
if (!verifySignature (body, signature, process.env .WEBHOOK_SECRET )) {
return new Response ("Unauthorized" , { status : 401 });
}
await ctx.runMutation (api.data .processWebhook , JSON .parse (body));
return new Response ("OK" );
});
Real-Time Subscription Leakage
export const allMessages = query ({
handler : async (ctx) => {
return await ctx.db .query ("messages" ).collect ();
},
});
export const myMessages = query ({
handler : async (ctx) => {
const userId = await getAuthUserId (ctx);
if (!userId) return [];
const myChannels = await ctx.db .query ("channelMembers" )
.filter (q => q.eq (q.field ("userId" ), userId))
.collect ();
const channelIds = myChannels.map (m => m.channelId );
return await ctx.db .query ("messages" )
.filter (q => q.or (...channelIds.map (id =>
q.eq (q.field ("channelId" ), id)
)))
.collect ();
},
});
Environment Variables
const apiKey = process.env .STRIPE_SECRET_KEY ;
export const callStripe = action ({
handler : async (ctx) => {
const apiKey = process.env .STRIPE_SECRET_KEY ;
if (!apiKey) throw new Error ("STRIPE_SECRET_KEY not configured" );
},
});
Note: Environment variables are only available in actions, not queries/mutations.
Common Vulnerabilities Summary Issue Where to Look Severity No auth check in query/mutation All query({ and mutation({ CRITICAL IDOR (no ownership check) Functions with document IDs in args HIGH Client-provided userId Args with v.id("users") HIGH Missing validators Functions without args: {} HIGH Public function for internal logic Sensitive business logic HIGH HTTP action without auth httpAction(HIGH Subscription data leak Queries returning collections MEDIUM Raw query/mutation (no custom fn) Not using userQuery/userMutation MEDIUM
Quick Audit Commands
rg "export const .* = query\(" convex/
rg "export const .* = mutation\(" convex/
rg -l "export const .* = (query|mutation)\(" convex/ | \
xargs rg -L "(getAuthUserId|getUserIdentity)"
rg 'userId: v\.id\("users"\)' convex/
rg "handler: async \(ctx\)" convex/ -g "*.ts"
rg "httpAction" convex/
rg "internalMutation|internalQuery|internalAction" convex/
Hardening Checklist