Cursor Security Best Practices: Building Secure Apps with AI

TL;DR

The #1 Cursor security best practice is reviewing every AI-generated function before committing. All 8 practices below take about 45 minutes. If you only do two of them, do these: check every generated function for hardcoded secrets, and confirm the endpoint actually checks authentication rather than just hiding the button.

"AI generates code fast. Security still needs a human reading it, function by function, before it ships."

Why Cursor Needs Security Best Practices

Cursor writes functional code in seconds. That's the point of it. But a model optimises for code that runs, not code that holds up against someone poking at it, and nothing in the loop closes that gap for you.

The encouraging part is how shallow most of the damage turns out to be. In scans of AI-built apps we see the same short list over and over: a key pasted into the client, an endpoint with no auth check, a table with no policy on it. None of those take long to fix once you know to look.

Best Practice 1: Review Every AI-Generated Function 2 min per function

Speed is where this goes wrong. Get into the habit of reading every generated block before you accept it:

Security Review Checklist for Generated Code

Before accepting Cursor suggestions:

  • No hardcoded API keys, tokens, or passwords
  • User input is validated before processing
  • Database queries use parameterized statements
  • Authentication checks exist on protected routes
  • Authorization verifies user owns requested resource
  • Error messages don't expose internal details

Example: Reviewing an API Endpoint

AI-generated code (has issues)
// Cursor might generate this
app.get('/api/user/:id', async (req, res) => {
  const user = await db.query(
    `SELECT * FROM users WHERE id = ${req.params.id}`
  );
  res.json(user);
});
Secure version
// Fixed with security best practices
app.get('/api/user/:id', authenticate, async (req, res) => {
  // Authorization: user can only access their own data
  if (req.user.id !== req.params.id && !req.user.isAdmin) {
    return res.status(403).json({ error: 'Access denied' });
  }

  // Parameterized query prevents SQL injection
  const user = await db.query(
    'SELECT id, email, name FROM users WHERE id = $1',
    [req.params.id]
  );

  if (!user) {
    return res.status(404).json({ error: 'Not found' });
  }

  res.json(user);
});

Best Practice 2: Configure .cursorignore Properly 5 min

Cursor sends code context to AI servers for processing. Protect sensitive files by excluding them from AI context:

.cursorignore (recommended configuration)
# Environment and secrets
.env
.env.*
*.pem
*.key
**/secrets/**
**/credentials/**

# Configuration with sensitive data
config/production.js
firebase-admin*.json
service-account*.json

# Proprietary code (optional)
src/core/algorithms/
lib/proprietary/

# Large files that waste context
node_modules/
dist/
*.log
*.sql

Important: .cursorignore only stops files being sent as AI context. It doesn't stop them being committed to git. You still need a proper .gitignore.

Best Practice 3: Use Secure Prompting Patterns Ongoing

What you ask for is what you get. Say the security requirement out loud in the prompt:

Prompting Patterns That Improve Security

Instead ofAsk for
"Create a login endpoint""Create a secure login endpoint with rate limiting, password hashing, and no sensitive data in errors"
"Add a delete user function""Add a delete user function with authentication check and authorization (admin or self only)"
"Query users from database""Query users using parameterized statements to prevent SQL injection"
"Create file upload""Create secure file upload with type validation, size limits, and sanitized filenames"

Best Practice 4: Enable Privacy Mode 1 min

Privacy Mode stops your code being used for model training. Turn it on for anything commercial:

  1. Open Cursor Settings (Cmd/Ctrl + ,)
  2. Navigate to Privacy settings
  3. Enable "Privacy Mode"
  4. Verify the privacy indicator appears in the status bar

Enterprise users: Cursor Business plans offer additional privacy controls including the option to use self-hosted models and stricter data retention policies.

Best Practice 5: Validate Environment Variables at Startup 10 min

Generated code reaches for environment variables constantly, and a missing one usually surfaces as a confusing runtime error hours later. Fail loudly at startup instead:

env-validation.js
// Validate required environment variables at startup
const requiredEnvVars = [
  'DATABASE_URL',
  'SESSION_SECRET',
  'STRIPE_SECRET_KEY',
];

function validateEnv() {
  const missing = requiredEnvVars.filter(
    (key) => !process.env[key]
  );

  if (missing.length > 0) {
    console.error('Missing required environment variables:');
    missing.forEach((key) => console.error(`  - ${key}`));
    process.exit(1);
  }
}

validateEnv();

Best Practice 6: Test Database Security Before Launch 15 min

If you're pairing Cursor with Supabase or Firebase, test the rules yourself. Never assume they took:

Supabase RLS Testing

Test RLS policies work correctly
-- Test as anonymous user (should fail for protected tables)
SET request.jwt.claim.sub = '';
SELECT * FROM private_data; -- Should return empty or error

-- Test as authenticated user
SET request.jwt.claim.sub = 'user-123';
SELECT * FROM user_data WHERE user_id = 'user-123'; -- Should work
SELECT * FROM user_data WHERE user_id = 'other-user'; -- Should fail

Best Practice 7: Implement Rate Limiting 10 min

Generated APIs almost never come with rate limiting. Add it:

Adding rate limiting to Express
import rateLimit from 'express-rate-limit';

// General API rate limit
const apiLimiter = rateLimit({
  windowMs: 15 * 60 * 1000, // 15 minutes
  max: 100, // 100 requests per window
  message: { error: 'Too many requests, try again later' }
});

// Stricter limit for auth endpoints
const authLimiter = rateLimit({
  windowMs: 15 * 60 * 1000,
  max: 5, // Only 5 login attempts per 15 minutes
  message: { error: 'Too many login attempts' }
});

app.use('/api/', apiLimiter);
app.use('/api/auth/', authLimiter);

Best Practice 8: Use Cursor Chat for Security Reviews 5 min per review

Point Cursor at your own code and make it argue with you:

Effective security review prompts
// In Cursor Chat, highlight code and ask:

"Review this code for security vulnerabilities including:
- SQL injection
- XSS vulnerabilities
- Authentication bypass
- Authorization issues
- Information disclosure in errors
- Missing input validation"

// Or for specific concerns:
"Does this endpoint properly validate that the
authenticated user owns the resource they are accessing?"

Common Cursor Security Mistakes

MistakeRiskFix
Accepting code without reviewVulnerabilities in productionReview every function before committing
Hardcoded test credentialsCredential exposureAlways use environment variables
No .cursorignore fileSecrets sent to AI serversConfigure .cursorignore immediately
Trusting CORS: "*" in generated codeCross-origin attacksSpecify allowed origins explicitly
Missing auth on new endpointsUnauthorized accessAdd auth middleware by default

Official Resources: For the latest information, see Cursor Documentation, Cursor Privacy Policy, and Cursor Security Overview.

Is Cursor safe for commercial projects?

Yes, with proper configuration. Enable Privacy Mode, configure .cursorignore for your sensitive files, and review AI-generated code before it ships. Plenty of companies run Cursor in production on exactly those terms.

Does Cursor store my code?

Cursor sends code context to AI servers so the model can answer. With Privacy Mode on, that code isn't used for training. Check Cursor's current privacy policy for the specifics on retention and handling, since those terms change.

How do I prevent Cursor from seeing secrets?

Create a .cursorignore file in your project root and add patterns for .env files, key files, and any directories containing sensitive configuration. This prevents these files from being sent as AI context.

Should I use Cursor for security-critical code?

You can use it for anything. Security-critical sections just need a second pair of eyes. Get another developer to read generated authentication, authorization, and data-handling code before it goes out.

Further Reading

Put these practices into action with our step-by-step guides.

Verify Your Cursor Security

Scan your Cursor project for common security issues in AI-generated code.

Best Practices

Cursor Security Best Practices: Building Secure Apps with AI