By default, Vite dev server can serve ANY file in your project directory, including:
server.js(backend source code).env(environment variables with secrets)config/,models/,routes/(backend logic)package.json(dependency information)
fs: {
// Only allow these directories to be served
allow: [
"./src", // Frontend source code
"./public", // Public assets
"./node_modules" // Dependencies (needed for imports)
],
// Explicitly deny sensitive files
deny: [
"**/.env*", // All environment files
"**/server.js", // Express server
"**/config/**", // MongoDB config
"**/models/**", // Mongoose models
"**/routes/**", // Express routes
"**/api/**", // Vercel serverless functions
"**/*.md", // Documentation
"**/package.json", // Package info
"**/vercel.json" // Vercel config
],
strict: true // Don't follow symlinks outside allowed dirs
}Only specific asset types are served:
assetsInclude: [
"**/*.png", "**/*.jpg", "**/*.jpeg",
"**/*.gif", "**/*.svg", "**/*.webp"
]This prevents serving arbitrary files as assets.
Test if backend files are accessible:
# Should return 403 Forbidden (Good ✅)
curl -I http://localhost:8080/server.js
# Should return 403 Forbidden (Good ✅)
curl -I http://localhost:8080/.env
# Should return 403 Forbidden (Good ✅)
curl -I http://localhost:8080/config/database.js
# Should work (Frontend assets ✅)
curl -I http://localhost:8080/| File/Directory | Protected | Method |
|---|---|---|
.env, .env.* |
✅ Yes | Vite deny list + .gitignore |
server.js |
✅ Yes | Vite deny list |
config/ |
✅ Yes | Vite deny list + not in allow list |
models/ |
✅ Yes | Vite deny list + not in allow list |
routes/ |
✅ Yes | Vite deny list + not in allow list |
api/ |
✅ Yes | Vite deny list + not in allow list |
package.json |
✅ Yes | Vite deny list |
vercel.json |
✅ Yes | Vite deny list |
*.md files |
✅ Yes | Vite deny list |
src/ |
❌ No | Intentionally public (frontend code) |
public/ |
❌ No | Intentionally public (static assets) |
-
Frontend Build
- Only
dist/folder is served (compiled frontend) - Original source code (
src/) is NOT accessible - No backend files are deployed to CDN
- Only
-
Backend (Serverless Functions)
- Files in
api/become serverless functions - Source code is NOT directly accessible
- Only HTTP endpoints work (e.g.,
/api/health)
- Files in
-
Environment Variables
- Stored encrypted in Vercel
- Never exposed to frontend
- Only accessible to serverless functions
Vercel Deployment:
├── dist/ # Frontend (CDN) - PUBLIC
│ ├── index.html
│ ├── assets/
│ └── ...
└── api/ # Serverless Functions - PRIVATE
├── health.js → /api/health
├── ecommerce-details/
│ ├── index.js → /api/ecommerce-details
│ └── [id].js → /api/ecommerce-details/:id
└── carts/
└── [cartId].js → /api/carts/:cartId
NOT DEPLOYED:
❌ server.js
❌ config/
❌ models/
❌ routes/
❌ .env
❌ src/ (original source)
After deploying to Vercel:
# These should return 404 (Good ✅)
curl https://your-app.vercel.app/server.js
curl https://your-app.vercel.app/.env
curl https://your-app.vercel.app/config/database.js
# These should work (API endpoints ✅)
curl https://your-app.vercel.app/api/health
curl https://your-app.vercel.app/api/ecommerce-details
# Frontend should work (✅)
curl https://your-app.vercel.app/File: .env (NEVER commit this!)
# .gitignore already includes:
*.env*Protections:
- ✅ Ignored by git (
.gitignore) - ✅ Blocked by Vite dev server (
fs.deny) - ✅ Not accessible via HTTP
Storage: Encrypted in Vercel Dashboard
Access:
- ✅ Only serverless functions can read them
- ❌ Frontend CANNOT access them
- ❌ Not included in client-side bundles
Setting Variables:
# Via Vercel Dashboard
Settings → Environment Variables
# Or via CLI
vercel env add MONGODB_URIFormat:
mongodb+srv://username:password@cluster.mongodb.net/database
Protections:
- ✅ Stored in
.env(not committed) - ✅ Encrypted in Vercel (production)
- ✅ Only backend can access it
Recommended Settings:
- Go to MongoDB Atlas → Network Access
- Option A (Most Secure): Whitelist only Vercel IPs
- Option B (Development): Allow all (
0.0.0.0/0)
Vercel IP Ranges:
All API functions include CORS headers:
res.setHeader('Access-Control-Allow-Origin', '*');For Production: Replace * with your actual domain:
res.setHeader('Access-Control-Allow-Origin', 'https://your-app.vercel.app');All API endpoints validate:
- ✅ MongoDB ObjectId format
- ✅ HTTP method restrictions
- ✅ Request body structure
- ✅ Allowed fields for updates
Errors NEVER expose:
- ❌ Database connection strings
- ❌ Internal file paths
- ❌ Stack traces (in production)
-
.envis in.gitignore - No hardcoded secrets in code
- No
console.log()with sensitive data - All API routes validate input
- Environment variables set in Vercel Dashboard
- MongoDB Network Access configured
- CORS origins restricted (if needed)
- Test all API endpoints work
- Test backend files are NOT accessible
- Test API endpoints work correctly
- Verify MongoDB connection works
- Check Vercel function logs for errors
Solution:
# Remove from git history
git rm --cached .env
git commit -m "Remove .env"
git pushThen rotate all secrets (MongoDB password, API tokens).
Solution:
- Never use
VITE_prefix for secrets - Only use
process.envin backend (/apifolder) - Frontend should call backend APIs, not external APIs directly
Solution:
- Already fixed with Vite
fs.denyconfiguration - Test with
curl http://localhost:8080/server.js
If you find a security vulnerability:
- DO NOT open a public GitHub issue
- Email the maintainer directly
- Include steps to reproduce
- Wait for a fix before disclosing publicly