The Rowguard demo includes a migration file API (/api/migrations) that provides filesystem access for educational purposes. This feature has the following security characteristics:
-
Local Development (
pnpm demo:dev)- Runs on
localhost:5173only - Not accessible from the internet
- Safe for learning and testing
- Runs on
-
Static Deployments (Vercel, Netlify, etc.)
- Production builds are static files only
- Vite plugin does NOT run in production builds
- Migration API is completely absent from deployed version
- Users see "SQL Only" mode (no filesystem access)
-
Exposing Dev Server to Internet
# ❌ DANGEROUS - DO NOT DO THIS vite dev --host 0.0.0.0This exposes filesystem write/delete access to anyone who can reach your IP.
-
Running Dev Server in Production
# ❌ DANGEROUS - DO NOT DO THIS NODE_ENV=production vite devThe dev server is not designed for production use.
-
Using Vite Preview in Production
# ❌ DANGEROUS - DO NOT USE FOR PRODUCTION HOSTING vite preview --host 0.0.0.0While the migration API won't work in preview, this is still not a production server.
The migration plugin only runs in Vite dev server and is excluded from production builds:
// Automatically disabled in production
if (config.command !== 'serve') {
console.warn('Plugin will not run in production builds.');
}All filenames are validated to prevent directory traversal attacks:
// Blocks: ../../../etc/passwd, /absolute/path, etc.
if (
filename.includes('..') ||
filename.includes('/') ||
filename.includes('\\')
) {
return error('Invalid filename');
}CORS is permissive in development for localhost testing but doesn't matter in production since the API doesn't exist.
When you run pnpm demo:build:
- Vite bundles to static files (HTML, CSS, JS)
- The migrations plugin never executes
- No backend endpoints exist
- No filesystem access possible
The public demo at https://rowguard-demo.vercel.app is completely safe because:
- ✅ It's a static build deployed to Vercel
- ✅ No backend server is running
- ✅ No filesystem access exists
- ✅ Migration API is not present in the build
- ✅ Users can only generate SQL (read-only operation)
-
Without Local Supabase: "Disconnected - SQL Only" badge
- Can generate SQL policies
- Cannot test against a database
- Cannot create migration files
-
With Local Supabase (if they clone and run locally):
- Full migration workflow
- Filesystem API (localhost only)
- Safe because it's on their own machine
# Build for production (static files only)
pnpm demo:build
# Deploy the dist/ folder to:
# - Vercel
# - Netlify
# - GitHub Pages
# - Any static hosting
# Or use Vercel CLI:
vercel deploy# Never do these in production:
vite dev --host 0.0.0.0 # Exposes dev server
NODE_ENV=production vite dev # Still a dev server
vite preview --host 0.0.0.0 # Not a production serverIf you want to add extra protection, you can:
- Check for localhost only:
// In the plugin
if (req.headers.host && !req.headers.host.startsWith('localhost')) {
return res.writeHead(403).end('Forbidden: Development only');
}- Add environment variable check:
if (process.env.DEMO_MIGRATION_API_ENABLED !== 'true') {
return; // Disable the API
}- Add rate limiting (for extra paranoia):
// Limit to 10 requests per minuteIf you discover a security vulnerability in Rowguard, please report it to:
- GitHub Security Advisory: https://github.com/supabase-community/rowguard/security/advisories
- Or open an issue with "Security:" prefix
✅ The public demo is safe - it's a static build with no backend
✅ Local development is safe - only accessible on localhost
🚨 Dev server should never be exposed to internet
🚨 Never use vite dev or vite preview in production
The migration API is a learning tool for local development only and does not pose a security risk when used as intended or when deployed as a static site.