Bolt.new Security Patterns
Common security vulnerabilities in apps generated by Bolt.new
Bolt.new's biggest security issue is hardcoded API keys and database credentials embedded directly in vibe coded apps. It also generates apps without authentication (CWE-306), input validation, or ownership checks. Great for vibe coding prototypes, but requires security review before production.
About Bolt.new
Bolt.new is a web-based AI app builder created by StackBlitz that went from $0 to $4M ARR within four weeks of launching with Claude, eventually reaching $20M ARR. It uses Claude Sonnet 4.5 (with Opus and Haiku options) to generate full-stack applications that run entirely in the browser using WebContainers, a Node.js runtime built with WebAssembly.
Bolt is designed for complete beginners, vibe coders, and non-technical founders who want to ship apps fast. Its philosophy is "ready to run" - vibe code that works immediately without configuration, environment setup, or security hardening. This makes it excellent for vibe coding and rapid prototyping, but vibe coded apps typically require security hardening before production deployment. The vulnerabilities commonly generated align with several categories in the OWASP Top 10.
What security issues does Bolt.new have?
These are the most common security patterns in Bolt.new-generated apps:
Hardcoded API Keys
HighBolt.new often embeds API keys and database connection strings directly in code. This happens because beginners don't know about environment variables, and Bolt optimizes for "ready to run" code that works immediately in the browser. Reference: CWE-798
// Bolt.new often generates this:
const supabase = createClient(
'https://abc123.supabase.co',
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImFiYzEyMyIsInJvbGUiOiJhbm9uIiwiaWF0IjoxNjQ0MjI2NDAwLCJleHAiOjE5NTk4MDI0MDB9.secretkey123'
);
// Database URL exposed
const db = new Client({
connectionString: 'postgresql://user:password@host:5432/database'
});// Secure version with environment variables:
const supabase = createClient(
import.meta.env.VITE_SUPABASE_URL,
import.meta.env.VITE_SUPABASE_ANON_KEY
);
// .env file (never commit this):
VITE_SUPABASE_URL=https://abc123.supabase.co
VITE_SUPABASE_ANON_KEY=your-anon-key-here
// Database URL from env
const db = new Client({
connectionString: process.env.DATABASE_URL
});Missing Authentication
CriticalBolt.new creates API endpoints and database queries without checking if a user is logged in. This happens because prompts rarely specify auth requirements, and authentication adds complexity that prevents code from running immediately. Reference: CWE-306
// Bolt.new generates functional but unprotected APIs:
export async function POST({ request }) {
const { userId, title, content } = await request.json();
const post = await db.posts.create({
data: { userId, title, content }
});
return json({ success: true, post });
}
// Anyone can create posts for any userId// Secure version with authentication:
export async function POST({ request, locals }) {
// Verify user is authenticated
if (!locals.user) {
return json({ error: 'Unauthorized' }, { status: 401 });
}
const { title, content } = await request.json();
// Use authenticated user ID, not client-provided
const post = await db.posts.create({
data: {
userId: locals.user.id,
title,
content
}
});
return json({ success: true, post });
}Missing Input Validation
HighBolt.new generates APIs that accept any input without validating types, formats, or lengths. Tutorial code and examples in training data typically skip validation to keep examples simple and focused on core functionality. Reference: CWE-20
// Bolt.new accepts input without validation:
app.post('/api/user', async (req, res) => {
const { email, name, age, bio } = req.body;
await db.users.create({
data: { email, name, age, bio }
});
res.json({ success: true });
});
// Accepts malformed emails, 999-character names, negative ages// Secure version with Zod validation:
import { z } from 'zod';
const userSchema = z.object({
email: z.string().email().max(255),
name: z.string().min(1).max(100),
age: z.number().int().min(13).max(120),
bio: z.string().max(500).optional()
});
app.post('/api/user', async (req, res) => {
const result = userSchema.safeParse(req.body);
if (!result.success) {
return res.status(400).json({
error: 'Invalid input',
details: result.error.issues
});
}
await db.users.create({ data: result.data });
res.json({ success: true });
});IDOR - Insecure Direct Object References
HighBolt.new creates APIs that trust client-provided IDs without verifying ownership. AI models don't inherently understand multi-tenant security or the concept that users should only access their own data. Reference: CWE-639
// Bolt.new trusts the ID from the client:
app.get('/api/invoice/:id', async (req, res) => {
const invoice = await db.invoices.findUnique({
where: { id: req.params.id }
});
res.json(invoice);
});
// User can view ANY invoice by changing the ID in URL// Secure version with ownership check:
app.get('/api/invoice/:id', async (req, res) => {
if (!req.user) {
return res.status(401).json({ error: 'Unauthorized' });
}
const invoice = await db.invoices.findFirst({
where: {
id: req.params.id,
userId: req.user.id // Only return if user owns it
}
});
if (!invoice) {
return res.status(404).json({ error: 'Invoice not found' });
}
res.json(invoice);
});Overly Permissive CORS
MediumBolt.new configures CORS to allow all origins so the frontend works immediately. This is the fastest path to a working app but exposes APIs to cross-origin attacks and CSRF vulnerabilities. Reference: CWE-942
// Bolt.new makes the API accessible from anywhere:
import cors from 'cors';
app.use(cors({
origin: '*',
credentials: true
}));
// Now any website can call your API and steal user data// Secure version with origin allowlist:
import cors from 'cors';
const allowedOrigins = [
'https://yourdomain.com',
'https://www.yourdomain.com',
'http://localhost:5173' // For development
];
app.use(cors({
origin: (origin, callback) => {
// Allow requests with no origin (mobile apps, Postman)
if (!origin) return callback(null, true);
if (allowedOrigins.includes(origin)) {
callback(null, true);
} else {
callback(new Error('Not allowed by CORS'));
}
},
credentials: true
}));Why Bolt.new generates these patterns
Bolt.new generates insecure vibe code patterns because of its design philosophy and target audience:
- Designed for beginners: Bolt's vibe coder users often don't know what environment variables are, how authentication works, or why input validation matters. According to research from Endor Labs, AI-generated code commonly includes hardcoded secrets and missing security controls
- "Ready to run" philosophy: Bolt optimizes for vibe code that works immediately in the browser without any configuration. Adding environment variables, auth middleware, or validation would prevent the app from running instantly
- Training data patterns: AI models learn from tutorials and example code that prioritize simplicity. According to Snyk's security research, most tutorials skip security to keep examples focused and understandable
- Speed over security: Bolt's value proposition is shipping MVPs in minutes. Security features add complexity and development time, which conflicts with the core vibe coding use case
Research from CrowdStrike found that AI-generated code frequently contains security vulnerabilities that require manual review. For vibe coders using Bolt, this means the vibe coded app might work perfectly in your browser but be completely insecure when deployed publicly.
How does Bolt.new compare to other AI tools?
Bolt.new optimizes for speed and beginner accessibility, which means it generates less secure code by default compared to tools like Cursor or Claude Code that give developers more control over the generation process.
| Tool | Security Posture | Target User | Top Issue | Deploy Speed | Best For |
|---|---|---|---|---|---|
| Bolt.new | Lowest by default | Beginners, founders | Hardcoded secrets | Fastest (one-click) | Rapid prototyping |
| v0 | Low-Medium | Designers, frontend devs | Client-side validation | Fast (export code) | UI prototyping |
| Cursor | Medium | Experienced devs | Missing validation | Medium (you deploy) | Production development |
| Claude Code | Medium-High | Terminal-native devs | Rate limiting | Medium (you deploy) | Refactoring, backend |
Key takeaway: Bolt optimizes for speed. Cursor and Claude Code give you more control, which typically results in more secure outcomes because you're reviewing more decisions. For production vibe coded apps, expect to spend more time on security review with Bolt than with other tools.
AI fix prompt for Bolt.new security issues
Copy this prompt and paste it into Bolt.new, Cursor, or Claude Code to automatically find and fix security vulnerabilities in your vibe coded project:
Review my codebase for these security issues and fix them:
1. **Hardcoded Secrets**: Move all API keys, database URLs, and credentials to environment variables using .env files. Search for patterns like:
- `const supabase = createClient('https://...',`
- `connectionString: 'postgresql://...`
- Any string containing 'key', 'secret', 'password', 'token'
2. **Missing Authentication**: Add authentication checks to all API routes that access user data. Return 401 if not authenticated.
- Check for routes using `async function POST` or `app.post` without auth checks
- Look for `await db.` queries without `locals.user` or `req.user` verification
3. **Missing Input Validation**: Add Zod validation to all API endpoints that accept user input. Validate types, formats, and constraints.
- Install Zod: `npm install zod`
- Add schemas for all request bodies
4. **IDOR Vulnerabilities**: In API routes that fetch data by ID, verify the current user owns that resource before returning it.
- Change `findUnique({ where: { id } })` to `findFirst({ where: { id, userId: user.id } })`
5. **Overly Permissive CORS**: Replace `origin: '*'` with an allowlist of your actual frontend domains.
For each fix:
- Show me the vulnerable code
- Show me the secure version
- Explain what changed and why
After fixing, search for remaining patterns:
- `origin: '*'`
- `createClient(..., '...')` (hardcoded keys)
- Routes without `if (!locals.user)` or `if (!req.user)`
Please proceed systematically through my codebase.This prompt works with any AI coding tool. It systematically searches for the five most common vulnerabilities in Bolt-generated vibe code and provides secure alternatives.
How to use Bolt.new securely
- Use for prototyping, not production:
Bolt is excellent for validating ideas, building MVPs, and learning how apps work. Plan for a security review phase before going live with real users.
- Move secrets to environment variables:
Before deploying, move all API keys, database URLs, and credentials to .env files. Most hosting platforms (Vercel, Netlify, Railway) provide environment variable management in their dashboards.
- Add authentication to every API:
Use Supabase Auth, Clerk, or Auth.js to add authentication. Verify the user is logged in before allowing any database operations.
- Add input validation with Zod:
Install Zod (
npm install zod) and validate all user input. Define schemas that match your database columns with proper types and constraints. - Add ownership checks:
For any endpoint that accesses user data by ID, verify the authenticated user owns that data. Never trust IDs sent from the client.
- Configure CORS properly:
Replace
origin: '*'with an allowlist of your actual domains. Include localhost for development. - Scan before deploying:
Run Vibeship Scanner to catch hardcoded secrets, missing auth, and other vulnerabilities automatically.
Scan your Bolt.new apps
Find hardcoded secrets, missing auth, and other security issues before deployment
Scan your code freeFrequently asked questions
Is Bolt.new safe to use?
Bolt.new is safe for prototyping and learning, but code generated by Bolt requires security review before production deployment. Bolt optimizes for speed and beginners, which means it generates functional code that often lacks authentication, input validation, and secure configuration. These patterns are fixable but must be addressed before going live.
What are the security risks of Bolt.new?
The main security risks are hardcoded API keys, missing authentication on APIs, lack of input validation, IDOR vulnerabilities where users can access other users' data, and overly permissive CORS. These patterns appear because Bolt prioritizes "ready to run" code that works immediately for beginners who may not understand security concepts.
Is Bolt.new safe for production?
No. Bolt.new is designed for rapid prototyping and MVP development, not production-ready applications. Code generated by Bolt typically requires significant security hardening before deployment. You should add authentication, input validation, rate limiting, and proper environment variable handling before launching.
Bolt.new vs Cursor - which is more secure?
Cursor generates slightly more secure code in some areas, particularly for developers who are already familiar with security patterns. Bolt is optimized for complete beginners and speed, which means it takes more shortcuts. However, both tools require manual security review before production deployment.
Should I use Bolt.new for my startup?
Yes for prototyping and MVPs to validate ideas quickly. No for production applications without security review. Bolt is excellent for vibe coders who want to ship fast with vibe coding, but you need to address the security patterns listed above before handling real user data or going public.