Cursor + Prisma + Vercel Security Blueprint

Share

To secure a Cursor + Prisma + Vercel stack, you need to: (1) store your DATABASE_URL in Vercel environment variables (never in code), (2) use Prisma's standard query methods which automatically prevent SQL injection, (3) avoid string interpolation in $queryRaw calls or use proper parameterization, (4) implement authorization checks in all API routes since Prisma lacks built-in RLS, and (5) create a .cursorignore file to prevent AI from accessing your .env files. This blueprint covers Prisma's security benefits, raw query dangers, and authorization patterns.

Setup Time2-3 hours

TL;DR

Prisma provides type-safe database access and prevents most SQL injection attacks by default. Key security tasks: store DATABASE_URL in Vercel environment variables, use Prisma's query methods (not raw SQL when possible), implement authorization checks in your API routes, and be careful with $queryRaw which bypasses Prisma's protections.

Platform Guides & Checklists

      Cursor Security Guide



      Prisma Security Guide



      Vercel Security Guide



      Pre-Launch Checklist

Stack Overview

Prisma is a type-safe ORM that generates a database client from your schema. This stack is excellent for type safety and developer experience:

ComponentRoleSecurity Benefit
CursorAI code editorType hints help catch errors
PrismaDatabase ORMType-safe queries prevent injection
VercelHostingSecure env vars, serverless functions

Part 1: Prisma Security Benefits Prisma

Built-in SQL Injection Protection Prisma

Prisma's query methods automatically parameterize inputs:

Safe Prisma query (injection protected)
// This is safe - Prisma parameterizes the input
const user = await prisma.user.findUnique({
  where: { email: userInput }  // Safe even if userInput is malicious
});

// Also safe
const posts = await prisma.post.findMany({
  where: {
    title: { contains: searchQuery },  // Parameterized
    authorId: userId  // Parameterized
  }
});

Danger: Raw Queries Prisma Cursor

The main injection risk in Prisma is using $queryRaw incorrectly:

DANGEROUS: String interpolation in raw query
// NEVER do this - SQL injection vulnerability
const users = await prisma.$queryRaw`
  SELECT * FROM users WHERE name = '${userInput}'
`;

// This bypasses Prisma's protection!
Safe raw query with parameters
// Safe: Use template literal without quotes
const users = await prisma.$queryRaw`
  SELECT * FROM users WHERE name = ${userInput}
`;
// Note: Template literal without quotes around ${userInput}

AI code risk: Cursor might generate raw SQL queries for complex operations. Always review any $queryRaw or $executeRaw usage for proper parameterization.

Part 2: Database Connection Security Prisma Vercel

.env (local development only)
# Never commit this file
DATABASE_URL="postgresql://user:password@host:5432/database?sslmode=require"

# For connection pooling with Prisma (recommended for serverless)
DATABASE_URL="postgresql://user:password@host:5432/database?pgbouncer=true"
DIRECT_URL="postgresql://user:password@host:5432/database"
prisma/schema.prisma
datasource db {
  provider  = "postgresql"
  url       = env("DATABASE_URL")
  directUrl = env("DIRECT_URL")  // For migrations
}

Part 3: Authorization Patterns Vercel

Prisma doesn't have built-in row-level security. Implement authorization in your application:

Authorization check pattern
// lib/auth.ts
export async function getAuthorizedPost(postId: string, userId: string) {
  const post = await prisma.post.findUnique({
    where: { id: postId }
  });

  if (!post) {
    throw new Error('Post not found');
  }

  if (post.authorId !== userId) {
    throw new Error('Not authorized');
  }

  return post;
}

// In API route
export async function PUT(request: Request) {
  const session = await getSession();
  if (!session) {
    return Response.json({ error: 'Unauthorized' }, { status: 401 });
  }

  const { id, title, content } = await request.json();
  await getAuthorizedPost(id, session.user.id);

  const updated = await prisma.post.update({
    where: { id },
    data: { title, content }
  });

  return Response.json(updated);
}

Security Checklist

Pre-Launch Checklist for Cursor + Prisma + Vercel

DATABASE_URL in Vercel env vars (not in code)

.env files in .gitignore

No string interpolation in $queryRaw

Authorization checks on all protected routes

Sensitive fields excluded from responses

Input validation with Zod or similar

Connection pooling configured for serverless

SSL required for database connection

.cursorignore excludes .env files

Alternative Stack Configurations

Cursor + Supabase + Vercel Swap Prisma for Supabase client with built-in RLS. Different ORM approach with PostgreSQL security.

      Cursor + PlanetScale + Vercel
      Prisma with PlanetScale MySQL. Same ORM security, different database backend.


      T3 Stack Security
      Full T3 stack with Prisma, tRPC, and Next.js. Type-safe end-to-end security.

Is Prisma safe from SQL injection?

Yes, when using Prisma's standard query methods. All inputs are automatically parameterized. The only risk is using $queryRaw with string interpolation, which bypasses Prisma's protections.

Do I need connection pooling on Vercel?

Yes, strongly recommended. Serverless functions can create many database connections. Use Prisma's built-in connection pooling or services like PgBouncer to prevent connection exhaustion.

Using Prisma with Cursor?

Scan your app for security issues in AI-generated code.

Start Free Scan
Security Blueprints

Cursor + Prisma + Vercel Security Blueprint