Skip to main content
ClaudeWave
Skill403 estrellas del repoactualizado 4mo ago

convex-security-check

This Claude Code skill provides a security audit checklist for Convex backend applications, systematically evaluating authentication configuration, function access controls, argument validation, row-level data access, and environment variable handling. Use this checklist when developing or reviewing Convex applications to identify potential security gaps before deployment to production.

Instalar en Claude Code
Copiar
git clone --depth 1 https://github.com/waynesutton/convexskills /tmp/convex-security-check && cp -r /tmp/convex-security-check/skills/convex-security-check ~/.claude/skills/convex-security-check
Después abre una sesión nueva de Claude Code; el skill carga automáticamente.

SKILL.md

# Convex Security Check

A quick security audit checklist for Convex applications covering authentication, function exposure, argument validation, row-level access control, and environment variable handling.

## Documentation Sources

Before implementing, do not assume; fetch the latest documentation:

- Primary: https://docs.convex.dev/auth
- Production Security: https://docs.convex.dev/production
- Functions Auth: https://docs.convex.dev/auth/functions-auth
- For broader context: https://docs.convex.dev/llms.txt

## Instructions

### Security Checklist

Use this checklist to quickly audit your Convex application's security:

#### 1. Authentication

- [ ] Authentication provider configured (Clerk, Auth0, etc.)
- [ ] All sensitive queries check `ctx.auth.getUserIdentity()`
- [ ] Unauthenticated access explicitly allowed where intended
- [ ] Session tokens properly validated

#### 2. Function Exposure

- [ ] Public functions (`query`, `mutation`, `action`) reviewed
- [ ] Internal functions use `internalQuery`, `internalMutation`, `internalAction`
- [ ] No sensitive operations exposed as public functions
- [ ] HTTP actions validate origin/authentication

#### 3. Argument Validation

- [ ] All functions have explicit `args` validators
- [ ] All functions have explicit `returns` validators
- [ ] No `v.any()` used for sensitive data
- [ ] ID validators use correct table names

#### 4. Row-Level Access Control

- [ ] Users can only access their own data
- [ ] Admin functions check user roles
- [ ] Shared resources have proper access checks
- [ ] Deletion functions verify ownership

#### 5. Environment Variables

- [ ] API keys stored in environment variables
- [ ] No secrets in code or schema
- [ ] Different keys for dev/prod environments
- [ ] Environment variables accessed only in actions

### Authentication Check

```typescript
// convex/auth.ts
import { query, mutation } from "./_generated/server";
import { v } from "convex/values";
import { ConvexError } from "convex/values";

// Helper to require authentication
async function requireAuth(ctx: QueryCtx | MutationCtx) {
  const identity = await ctx.auth.getUserIdentity();
  if (!identity) {
    throw new ConvexError("Authentication required");
  }
  return identity;
}

// Secure query pattern
export const getMyProfile = query({
  args: {},
  returns: v.union(v.object({
    _id: v.id("users"),
    name: v.string(),
    email: v.string(),
  }), v.null()),
  handler: async (ctx) => {
    const identity = await requireAuth(ctx);
    
    return await ctx.db
      .query("users")
      .withIndex("by_tokenIdentifier", (q) => 
        q.eq("tokenIdentifier", identity.tokenIdentifier)
      )
      .unique();
  },
});
```

### Function Exposure Check

```typescript
// PUBLIC - Exposed to clients (review carefully!)
export const listPublicPosts = query({
  args: {},
  returns: v.array(v.object({ /* ... */ })),
  handler: async (ctx) => {
    // Anyone can call this - intentionally public
    return await ctx.db
      .query("posts")
      .withIndex("by_public", (q) => q.eq("isPublic", true))
      .collect();
  },
});

// INTERNAL - Only callable from other Convex functions
export const _updateUserCredits = internalMutation({
  args: { userId: v.id("users"), amount: v.number() },
  returns: v.null(),
  handler: async (ctx, args) => {
    // This cannot be called directly from clients
    await ctx.db.patch(args.userId, {
      credits: args.amount,
    });
    return null;
  },
});
```

### Argument Validation Check

```typescript
// GOOD: Strict validation
export const createPost = mutation({
  args: {
    title: v.string(),
    content: v.string(),
    category: v.union(
      v.literal("tech"),
      v.literal("news"),
      v.literal("other")
    ),
  },
  returns: v.id("posts"),
  handler: async (ctx, args) => {
    const identity = await requireAuth(ctx);
    return await ctx.db.insert("posts", {
      ...args,
      authorId: identity.tokenIdentifier,
    });
  },
});

// BAD: Weak validation
export const createPostUnsafe = mutation({
  args: {
    data: v.any(), // DANGEROUS: Allows any data
  },
  returns: v.id("posts"),
  handler: async (ctx, args) => {
    return await ctx.db.insert("posts", args.data);
  },
});
```

### Row-Level Access Control Check

```typescript
// Verify ownership before update
export const updateTask = mutation({
  args: {
    taskId: v.id("tasks"),
    title: v.string(),
  },
  returns: v.null(),
  handler: async (ctx, args) => {
    const identity = await requireAuth(ctx);
    
    const task = await ctx.db.get(args.taskId);
    
    // Check ownership
    if (!task || task.userId !== identity.tokenIdentifier) {
      throw new ConvexError("Not authorized to update this task");
    }
    
    await ctx.db.patch(args.taskId, { title: args.title });
    return null;
  },
});

// Verify ownership before delete
export const deleteTask = mutation({
  args: { taskId: v.id("tasks") },
  returns: v.null(),
  handler: async (ctx, args) => {
    const identity = await requireAuth(ctx);
    
    const task = await ctx.db.get(args.taskId);
    
    if (!task || task.userId !== identity.tokenIdentifier) {
      throw new ConvexError("Not authorized to delete this task");
    }
    
    await ctx.db.delete(args.taskId);
    return null;
  },
});
```

### Environment Variables Check

```typescript
// convex/actions.ts
"use node";

import { action } from "./_generated/server";
import { v } from "convex/values";

export const sendEmail = action({
  args: {
    to: v.string(),
    subject: v.string(),
    body: v.string(),
  },
  returns: v.object({ success: v.boolean() }),
  handler: async (ctx, args) => {
    // Access API key from environment
    const apiKey = process.env.RESEND_API_KEY;
    
    if (!apiKey) {
      throw new Error("RESEND_API_KEY not configured");
    }
    
    const response = await fetch("https://api.resend.com/emails", {
      method: "POST",
      headers: {
        "Authorization": `Bearer ${apiKey}
avoid-feature-creepSkill

Prevent feature creep when building software, apps, and AI-powered products. Use this skill when planning features, reviewing scope, building MVPs, managing backlogs, or when a user says "just one more feature." Helps developers and AI agents stay focused, ship faster, and avoid bloated products.

convex-agentsSkill

Building AI agents with the Convex Agent component including thread management, tool integration, streaming responses, RAG patterns, and workflow orchestration

convex-best-practicesSkill

Guidelines for building production-ready Convex apps covering function organization, query patterns, validation, TypeScript usage, error handling, and the Zen of Convex design philosophy

convex-component-authoringSkill

How to create, structure, and publish self-contained Convex components with proper isolation, exports, and dependency management

convex-cron-jobsSkill

Scheduled function patterns for background tasks including interval scheduling, cron expressions, job monitoring, retry strategies, and best practices for long-running tasks

convex-file-storageSkill

Complete file handling including upload flows, serving files via URL, storing generated files from actions, deletion, and accessing file metadata from system tables

convex-functionsSkill

Writing queries, mutations, actions, and HTTP actions with proper argument validation, error handling, internal functions, and runtime considerations

convex-http-actionsSkill

External API integration and webhook handling including HTTP endpoint routing, request/response handling, authentication, CORS configuration, and webhook signature validation