Antoine Duno
Founder of ZeriFlow · 10 years fullstack engineering · About the author
Key Takeaways
- You've built your app with Cursor. It works. Now audit it for security before real users touch it — here's the exact process, from headers to hardcoded secrets.
- Includes copy-paste code examples and step-by-step instructions.
- Free automated scan available to verify your implementation.
You built your app with Cursor. The features work. The UI looks good. You are ready to ship.
Before you do, spend 30 minutes on security. Not because Cursor writes bad code — it writes functional code. But functional and secure are two different things, and Cursor consistently optimizes for the first one. Here is the exact process to audit a Cursor-built app before real users touch it.
Step 1: Run a ZeriFlow Scan First (60 Seconds)
Is your site actually secure?
Run a free check — 60 seconds
Before opening a single file, deploy your app and run a free scan at zeriflow.com/free-scan.
The scan checks your deployed URL for: - Missing security headers (X-Frame-Options, CSP, HSTS, etc.) - TLS configuration issues - Exposed sensitive endpoints - Cookie security flags - CORS misconfigurations
Start with anything flagged as Critical or High. Note your score before fixing — you want at least 80/100 before launch.
Step 2: Check Every API Route for Authentication
Cursor default pattern when generating API routes is to write the happy path and skip authentication guards unless you explicitly asked for them.
Navigate to app/api/ (for Next.js App Router). Look for this pattern:
// Cursor-generated route — no auth check
export async function GET(request) {
const data = await prisma.user.findMany()
return Response.json(data)
}This route returns all users to anyone who calls it, authenticated or not. The correct pattern:
import { getServerSession } from 'next-auth'
import { authOptions } from '@/lib/auth'
export async function GET(request) {
const session = await getServerSession(authOptions)
if (!session) {
return Response.json({ error: 'Unauthorized' }, { status: 401 })
}
const data = await prisma.userProfile.findUnique({
where: { userId: session.user.id }
})
return Response.json(data)
}Go through every route in app/api/ and verify that routes handling sensitive data have this check at the top.
Step 3: Search for Hardcoded Secrets
Cursor uses realistic-looking placeholder values when generating code. Run this from your project root:
git grep -iE "api[_-]?key|secret|password|token|private[_-]?key"Also check git history:
git log -p --all | grep -iE "api[_-]?key|secret=" | head -50If you find real credentials in git history, rotate them immediately — the credential is compromised from the moment it was committed.
The rule: Every secret goes in .env.local (development) or environment variables in your deployment platform (production).
Step 4: Fix Security Headers
Cursor does not generate security headers. Add this to next.config.js:
const securityHeaders = [
{ key: 'X-DNS-Prefetch-Control', value: 'on' },
{ key: 'Strict-Transport-Security', value: 'max-age=63072000; includeSubDomains; preload' },
{ key: 'X-Frame-Options', value: 'SAMEORIGIN' },
{ key: 'X-Content-Type-Options', value: 'nosniff' },
{ key: 'Referrer-Policy', value: 'strict-origin-when-cross-origin' },
{ key: 'Permissions-Policy', value: 'camera=(), microphone=(), geolocation=()' },
]
module.exports = {
async headers() {
return [{ source: '/(.*)', headers: securityHeaders }]
},
}After adding headers, run the ZeriFlow scan again to confirm they are applied correctly.
Step 5: Verify CORS Configuration
Cursor frequently generates CORS with wildcard origins:
// Cursor-generated — WRONG for production
app.use(cors({ origin: '*' }))Fix it:
app.use(cors({
origin: process.env.ALLOWED_ORIGIN || 'https://yourdomain.com',
credentials: true,
methods: ['GET', 'POST', 'PUT', 'DELETE'],
allowedHeaders: ['Content-Type', 'Authorization'],
}))Step 6: Audit Dependencies
npm audit
npm audit fix --audit-level=highPay attention to Critical and High severity vulnerabilities. Update any package with known security issues before going to production.
Summary
- 1ZeriFlow scan on your deployed URL — fix all Critical findings
- 2Every API route has an auth check where required
- 3No hardcoded secrets in code or git history
- 4Security headers added to
next.config.js - 5CORS restricted to your production domain
- 6
npm auditrun and Critical/High vulnerabilities addressed
Run the ZeriFlow scan at the start and again at the end to measure your improvement. A score above 80 means you have covered the major deployment-level security issues that automated scanning can detect.
Verify your AI-generated app is production-ready.
80+ security checks in 60 seconds — free, no account needed.