[{"data":1,"prerenderedAt":360},["ShallowReactive",2],{"blog-blueprints/bolt-mongodb":3},{"id":4,"title":5,"body":6,"category":340,"date":341,"dateModified":341,"description":342,"draft":343,"extension":344,"faq":345,"featured":343,"headerVariant":346,"image":345,"keywords":345,"meta":347,"navigation":348,"ogDescription":349,"ogTitle":345,"path":350,"readTime":351,"schemaOrg":352,"schemaType":353,"seo":354,"sitemap":355,"stem":356,"tags":357,"twitterCard":358,"__hash__":359},"blog/blog/blueprints/bolt-mongodb.md","Bolt.new + MongoDB Security Blueprint",{"type":7,"value":8,"toc":320},"minimark",[9,20,24,30,35,38,105,109,114,117,132,136,145,158,162,166,175,179,188,192,195,204,208,217,221,226,229,232,235,238,241,244,247,250,263,289,308],[10,11,12],"blueprint-summary",{},[13,14,15,19],"p",{},[16,17,18],"strong",{},"To secure a Bolt.new + MongoDB stack,"," you need to: (1) validate all query inputs to prevent NoSQL injection attacks where user input can be objects instead of strings, (2) store connection strings in environment variables rather than code, (3) implement application-level authorization since MongoDB lacks row-level security, and (4) restrict network access to your MongoDB instance. This blueprint covers the unique security patterns required for document databases.",[21,22],"blueprint-meta",{"time":23},"1-2 hours",[25,26,27],"tldr",{},[13,28,29],{},"Bolt-generated MongoDB apps often have NoSQL injection vulnerabilities and missing authorization checks. Key fixes: validate all query inputs (user input can be objects, not just strings), store connection strings in environment variables, implement application-level authorization, and never expose MongoDB connection strings in client code.",[31,32,34],"h2",{"id":33},"mongodb-security-with-boltnew","MongoDB Security with Bolt.new",[13,36,37],{},"MongoDB requires different security patterns than SQL databases:",[39,40,41,57],"table",{},[42,43,44],"thead",{},[45,46,47,51,54],"tr",{},[48,49,50],"th",{},"Common Bolt Pattern",[48,52,53],{},"Security Issue",[48,55,56],{},"Fix",[58,59,60,72,83,94],"tbody",{},[45,61,62,66,69],{},[63,64,65],"td",{},"Direct user input in queries",[63,67,68],{},"NoSQL injection",[63,70,71],{},"Input validation with Zod/Joi",[45,73,74,77,80],{},[63,75,76],{},"Connection string in code",[63,78,79],{},"Credential exposure",[63,81,82],{},"Environment variables",[45,84,85,88,91],{},[63,86,87],{},"No authorization checks",[63,89,90],{},"Data leakage",[63,92,93],{},"App-level auth middleware",[45,95,96,99,102],{},[63,97,98],{},"Find without filters",[63,100,101],{},"Full collection exposure",[63,103,104],{},"Always scope to user",[31,106,108],{"id":107},"part-1-preventing-mongodb-nosql-injection","Part 1: Preventing MongoDB NoSQL Injection",[110,111,113],"h3",{"id":112},"the-problem","The Problem",[13,115,116],{},"Bolt-generated queries often use user input directly:",[118,119,121],"code-block",{"label":120},"VULNERABLE: Direct user input in query",[122,123,128],"pre",{"className":124,"code":126,"language":127},[125],"language-text","// Bolt might generate this\napp.get('/api/user', async (req, res) => {\n  const user = await db.collection('users').findOne({\n    username: req.query.username  // Can be an object!\n  });\n  res.json(user);\n});\n\n// Attack: ?username[$ne]=null returns first user\n// Attack: ?username[$gt]= returns users alphabetically\n","text",[129,130,126],"code",{"__ignoreMap":131},"",[110,133,135],{"id":134},"the-fix","The Fix",[118,137,139],{"label":138},"SECURE: Validated input",[122,140,143],{"className":141,"code":142,"language":127},[125],"import { z } from 'zod';\n\nconst usernameSchema = z.string().min(1).max(50);\n\napp.get('/api/user', async (req, res) => {\n  // Validate input is a string\n  const result = usernameSchema.safeParse(req.query.username);\n\n  if (!result.success) {\n    return res.status(400).json({ error: 'Invalid username' });\n  }\n\n  const user = await db.collection('users').findOne({\n    username: result.data  // Guaranteed string\n  });\n\n  if (!user) {\n    return res.status(404).json({ error: 'User not found' });\n  }\n\n  // Remove sensitive fields\n  const { password, ...safeUser } = user;\n  res.json(safeUser);\n});\n",[129,144,142],{"__ignoreMap":131},[146,147,148],"warning-box",{},[13,149,150,153,154,157],{},[16,151,152],{},"Critical:"," In Express/Node.js, query parameters can be objects if formatted as ",[129,155,156],{},"?key[$operator]=value",". Always validate type before using in MongoDB queries.",[31,159,161],{"id":160},"part-2-mongodb-connection-string-security","Part 2: MongoDB Connection String Security",[110,163,165],{"id":164},"check-for-exposed-credentials","Check for Exposed Credentials",[118,167,169],{"label":168},"Search exported code",[122,170,173],{"className":171,"code":172,"language":127},[125],"# Look for hardcoded connection strings\ngrep -r \"mongodb\" . --include=\"*.ts\" --include=\"*.js\"\ngrep -r \"mongodb+srv\" .\n\n# Should find only:\n# process.env.MONGODB_URI or similar\n",[129,174,172],{"__ignoreMap":131},[110,176,178],{"id":177},"proper-configuration","Proper Configuration",[118,180,182],{"label":181},"lib/mongodb.ts - Secure setup",[122,183,186],{"className":184,"code":185,"language":127},[125],"import { MongoClient } from 'mongodb';\n\nconst uri = process.env.MONGODB_URI;\n\nif (!uri) {\n  throw new Error('MONGODB_URI environment variable not set');\n}\n\nconst client = new MongoClient(uri);\n\nlet db: Db | null = null;\n\nexport async function getDb() {\n  if (!db) {\n    await client.connect();\n    db = client.db();  // Uses database from connection string\n  }\n  return db;\n}\n",[129,187,185],{"__ignoreMap":131},[31,189,191],{"id":190},"part-3-authorization-middleware","Part 3: Authorization Middleware",[13,193,194],{},"MongoDB doesn't have row-level security. Implement it in your application:",[118,196,198],{"label":197},"middleware/auth.ts",[122,199,202],{"className":200,"code":201,"language":127},[125],"import { Request, Response, NextFunction } from 'express';\nimport jwt from 'jsonwebtoken';\n\nexport interface AuthRequest extends Request {\n  user?: { id: string; email: string };\n}\n\nexport function requireAuth(\n  req: AuthRequest,\n  res: Response,\n  next: NextFunction\n) {\n  const token = req.headers.authorization?.replace('Bearer ', '');\n\n  if (!token) {\n    return res.status(401).json({ error: 'No token provided' });\n  }\n\n  try {\n    const decoded = jwt.verify(token, process.env.JWT_SECRET!);\n    req.user = decoded as { id: string; email: string };\n    next();\n  } catch {\n    return res.status(401).json({ error: 'Invalid token' });\n  }\n}\n",[129,203,201],{"__ignoreMap":131},[110,205,207],{"id":206},"using-auth-in-routes","Using Auth in Routes",[118,209,211],{"label":210},"routes/posts.ts - Scoped queries",[122,212,215],{"className":213,"code":214,"language":127},[125],"import { Router } from 'express';\nimport { ObjectId } from 'mongodb';\nimport { requireAuth, AuthRequest } from '../middleware/auth';\nimport { getDb } from '../lib/mongodb';\n\nconst router = Router();\n\n// Get user's own posts only\nrouter.get('/', requireAuth, async (req: AuthRequest, res) => {\n  const db = await getDb();\n\n  const posts = await db.collection('posts')\n    .find({ userId: req.user!.id })\n    .toArray();\n\n  res.json(posts);\n});\n\n// Update with ownership check\nrouter.put('/:id', requireAuth, async (req: AuthRequest, res) => {\n  const db = await getDb();\n\n  const post = await db.collection('posts').findOne({\n    _id: new ObjectId(req.params.id)\n  });\n\n  if (!post) {\n    return res.status(404).json({ error: 'Post not found' });\n  }\n\n  if (post.userId !== req.user!.id) {\n    return res.status(403).json({ error: 'Not authorized' });\n  }\n\n  await db.collection('posts').updateOne(\n    { _id: new ObjectId(req.params.id) },\n    { $set: { title: req.body.title, content: req.body.content } }\n  );\n\n  res.json({ success: true });\n});\n\nexport default router;\n",[129,216,214],{"__ignoreMap":131},[31,218,220],{"id":219},"security-checklist","Security Checklist",[222,223,225],"h4",{"id":224},"post-export-checklist-for-bolt-mongodb","Post-Export Checklist for Bolt + MongoDB",[13,227,228],{},"No hardcoded connection strings",[13,230,231],{},"MONGODB_URI in environment variables",[13,233,234],{},"Input validation on all query parameters",[13,236,237],{},"Authorization middleware on protected routes",[13,239,240],{},"Queries scoped to authenticated user",[13,242,243],{},"Sensitive fields excluded from responses",[13,245,246],{},"MongoDB user has minimal permissions",[13,248,249],{},"Network access restricted (Atlas/cloud)",[251,252,253,257],"stack-comparison",{},[110,254,256],{"id":255},"alternative-stacks-to-consider","Alternative Stacks to Consider",[122,258,261],{"className":259,"code":260,"language":127},[125],"      **Bolt.new + Supabase**\n      PostgreSQL with built-in RLS protection\n\n\n      **Bolt.new + PlanetScale**\n      MySQL with branching workflows\n\n\n      **Bolt.new + Convex**\n      TypeScript-native database alternative\n",[129,262,260],{"__ignoreMap":131},[264,265,266,277,283],"faq-section",{},[267,268,270],"faq-item",{"question":269},"What's NoSQL injection?",[13,271,272,273,276],{},"Unlike SQL injection (which uses strings), NoSQL injection exploits MongoDB's query operators. Attackers send objects like ",[129,274,275],{},"{$ne: null}"," instead of strings, modifying query logic.",[267,278,280],{"question":279},"Should I use Mongoose with Bolt-generated code?",[13,281,282],{},"Mongoose adds schema validation which helps prevent injection. If Bolt generated native MongoDB driver code, consider adding Mongoose or Zod validation to ensure type safety.",[267,284,286],{"question":285},"How do I restrict MongoDB network access?",[13,287,288],{},"In MongoDB Atlas, go to Network Access and remove 0.0.0.0/0. Add only your deployment server's IP addresses. This prevents direct database access even if credentials leak.",[290,291,292,298,303],"related-articles",{},[293,294],"related-card",{"description":295,"href":296,"title":297},"Similar stack with Cursor","/blog/blueprints/cursor-mongodb-railway","Cursor + MongoDB + Railway",[293,299],{"description":300,"href":301,"title":302},"Deep dive into MongoDB","/blog/guides/mongodb","MongoDB Security Guide",[293,304],{"description":305,"href":306,"title":307},"PostgreSQL alternative","/blog/blueprints/bolt-supabase","Bolt + Supabase",[309,310,313,317],"cta-box",{"href":311,"label":312},"/","Start Free Scan",[31,314,316],{"id":315},"exported-a-bolt-mongodb-app","Exported a Bolt + MongoDB app?",[13,318,319],{},"Scan for NoSQL injection and authorization issues.",{"title":131,"searchDepth":321,"depth":321,"links":322},2,[323,324,329,333,336,339],{"id":33,"depth":321,"text":34},{"id":107,"depth":321,"text":108,"children":325},[326,328],{"id":112,"depth":327,"text":113},3,{"id":134,"depth":327,"text":135},{"id":160,"depth":321,"text":161,"children":330},[331,332],{"id":164,"depth":327,"text":165},{"id":177,"depth":327,"text":178},{"id":190,"depth":321,"text":191,"children":334},[335],{"id":206,"depth":327,"text":207},{"id":219,"depth":321,"text":220,"children":337},[338],{"id":255,"depth":327,"text":256},{"id":315,"depth":321,"text":316},"blueprints","2026-01-28","Security guide for Bolt.new + MongoDB stack. Secure connection strings, prevent NoSQL injection, implement authorization, and protect your Bolt-generated MongoDB app.",false,"md",null,"purple",{},true,"Complete security configuration for MongoDB apps built with Bolt.new.","/blog/blueprints/bolt-mongodb","10 min read","[object Object]","Article",{"title":5,"description":342},{"loc":350},"blog/blueprints/bolt-mongodb",[],"summary_large_image","8iZBLzpRJUem7_Z0w8Rf_SQ3rTO3NhIGlZoL-HdjIl8",1775843932857]