Environment Variables
Environment variables are key-value pairs set outside your application code that store configuration values and secrets, keeping sensitive data like API keys and database passwords out of source code.
Understanding Environment Variables
Environment variables separate configuration from code, allowing the same application to run in different environments (development, staging, production) with different settings. They are the standard mechanism for injecting secrets into applications without hardcoding them in source files that get committed to version control.
In Node.js applications, environment variables are accessed via process.env. The dotenv library loads variables from .env files during local development. In production, hosting platforms like Render, Vercel, and Heroku provide dashboards to set environment variables that are injected at runtime. The .env file should never be committed to Git — it belongs in .gitignore.
A critical distinction in modern frameworks is between server-side and client-side environment variables. Next.js exposes variables prefixed with NEXT_PUBLIC_ in the browser bundle. Vite uses VITE_. Create React App uses REACT_APP_. Variables without these prefixes remain server-side only. Putting a secret key in a NEXT_PUBLIC_ variable means it ships to every user's browser in the JavaScript bundle.
Best practices include using .env.example files (with placeholder values) to document required variables without exposing real values, using different .env files for each environment (.env.development, .env.production), never logging environment variables in error handlers or debug output, and validating that required environment variables are present at application startup rather than failing silently when they are undefined.
Why This Matters for Vibe-Coded Apps
AI-generated code frequently hardcodes secrets directly or places them in the wrong type of environment variable. A common AI pattern is putting a database URL or API secret key in NEXT_PUBLIC_DATABASE_URL, which exposes it to every user. Vibe coders who are moving quickly may not understand the significance of the NEXT_PUBLIC_ prefix.
When an AI generates environment-dependent code, always verify that secrets go in non-prefixed variables and are only accessed in server-side code (API routes, server components, getServerSideProps). If the AI puts a secret in a client-accessible variable, the fix is straightforward: remove the public prefix and move the usage to a server-side context.
Real-World Examples
Docker .env File Exposure
Thousands of Docker containers have been found serving .env files through their web servers because the entire application directory, including the .env file, was set as the web root. Automated scanners routinely check for /.env on every web server they encounter.
Next.js NEXT_PUBLIC_ Confusion
Multiple production applications have exposed database credentials, Stripe secret keys, and internal API tokens by prefixing them with NEXT_PUBLIC_. Because these values are embedded in the JavaScript bundle sent to browsers, they appear in view-source and can be extracted by anyone visiting the site.
Heroku Environment Variable Leak (2022)
Compromised OAuth tokens allowed attackers to access Heroku's internal systems and exfiltrate environment variables from customer applications. This highlighted that environment variables, while better than hardcoded secrets, are still vulnerable if the hosting platform itself is compromised.
Frequently Asked Questions
What is the difference between .env and .env.local?
The naming conventions vary by framework. In Next.js, .env contains defaults for all environments, .env.local contains local overrides (not committed to Git), .env.development and .env.production contain environment-specific values. .env.local always takes precedence. The key rule is that any file with actual secrets should be in .gitignore. Use .env.example with placeholder values to document required variables for other developers.
How do I know if an environment variable is exposed to the browser?
Check the prefix. In Next.js, NEXT_PUBLIC_ variables are bundled into client-side JavaScript. In Vite, VITE_ variables are exposed. In Create React App, REACT_APP_ variables are public. Variables without these prefixes are server-side only. You can also search your built JavaScript bundles (the .next/static or dist directories) for the variable value to confirm whether it appears in client code.
Should I use a .env file in production?
No. In production, environment variables should be set through your hosting platform's configuration (Render, Vercel, Heroku dashboards, or infrastructure-as-code tools). Deploying .env files to production servers creates a risk of exposure through misconfigured web servers, backup files, or directory traversal vulnerabilities. Platform-injected environment variables are more secure and easier to rotate.
How do I handle environment variables in Docker?
Use Docker's --env-file flag or environment section in docker-compose.yml to inject variables at runtime. Never include .env files in Docker images via COPY commands — they will be baked into every layer. Use Docker secrets for sensitive values in Docker Swarm, or integrate with a secret management service. Ensure your .dockerignore includes .env files to prevent accidental inclusion.
Is Your App Protected?
VAS automatically scans for vulnerabilities related to environment variables and provides detailed remediation guidance. Our scanner targets issues common in AI-generated applications.
Scans from $5, results in minutes. Get actionable fixes tailored to your stack.
Get Starter Scan