The .env File Trap: Why Your Next.js Secrets Keep Ending Up in the Browser
Introduction to the .env File Trap
When building Next.js applications with tools like Cursor, Lovable, Bolt, v0, or Replit, it's common to store sensitive data like API keys and database credentials in a .env file. However, if not handled properly, these secrets can end up being exposed to the browser, posing a significant security risk. The main question is: why do Next.js secrets keep ending up in the browser? The answer lies in how Next.js handles environment variables.
By default, Next.js exposes all environment variables to the browser, unless they are prefixed with NEXT_PUBLIC_. This means that if you have a .env file containing sensitive data, it will be sent to the client-side, making it accessible to anyone who inspects the browser's source code.
The Risk of Exposed Secrets
Exposed secrets can lead to severe security breaches, including unauthorized access to your database, API, or other sensitive systems. For example, if your .env file contains a database password, an attacker could use it to gain access to your database and steal or modify sensitive data.
To illustrate the issue, consider the following example:
// .env file
DB_PASSWORD=mysecretpassword
// next.js page
import { useState, useEffect } from 'react';
function HomePage() {
const [data, setData] = useState([]);
useEffect(() => {
fetch('/api/data')
.then(response => response.json())
.then(data => setData(data));
}, []);
return {data.map(item => {item.name})};
}
// api route
import { NextApiRequest, NextApiResponse } from 'next';
const getData = (req: NextApiRequest, res: NextApiResponse) => {
const dbPassword = process.env.DB_PASSWORD; // exposed to the browser
// use dbPassword to connect to the database
};
In this example, the DB_PASSWORD environment variable is exposed to the browser, making it accessible to anyone who inspects the browser's source code.
How to Fix the .env File Trap
To fix the .env file trap, you need to ensure that sensitive environment variables are not exposed to the browser. One way to do this is to use a separate environment file for sensitive data, such as a secrets.json file, and load it only on the server-side.
Here's an example of how you can do this:
// secrets.json file
{
"DB_PASSWORD": "mysecretpassword"
}
// next.js page
import { useState, useEffect } from 'react';
function HomePage() {
const [data, setData] = useState([]);
useEffect(() => {
fetch('/api/data')
.then(response => response.json())
.then(data => setData(data));
}, []);
return {data.map(item => {item.name})};
}
// api route
import { NextApiRequest, NextApiResponse } from 'next';
import secrets from '../secrets.json';
const getData = (req: NextApiRequest, res: NextApiResponse) => {
const dbPassword = secrets.DB_PASSWORD; // not exposed to the browser
// use dbPassword to connect to the database
};
In this example, the secrets.json file is loaded only on the server-side, and the DB_PASSWORD is not exposed to the browser.
Using Environment Variables with Next.js
Next.js provides a built-in way to handle environment variables using the env object. You can use the env object to access environment variables in your code.
Here's an example:
// next.js page
import { useState, useEffect } from 'react';
function HomePage() {
const [data, setData] = useState([]);
useEffect(() => {
fetch('/api/data')
.then(response => response.json())
.then(data => setData(data));
}, []);
return {data.map(item => {item.name})};
}
// api route
import { NextApiRequest, NextApiResponse } from 'next';
const getData = (req: NextApiRequest, res: NextApiResponse) => {
const dbName = process.env.NEXT_PUBLIC_DB_NAME; // exposed to the browser
const dbPassword = process.env.DB_PASSWORD; // not exposed to the browser
// use dbName and dbPassword to connect to the database
};
In this example, the NEXT_PUBLIC_DB_NAME environment variable is exposed to the browser, while the DB_PASSWORD environment variable is not.
Automating Security Scans with SecuriSky
To detect security issues like the .env file trap, you can use a security scanner like SecuriSky. SecuriSky can automatically scan your code for security vulnerabilities and provide recommendations for fixing them.
Quick Fix Checklist
env object to access environment variables in your codeNEXT_PUBLIC_Try it free
Scan your app for these issues now
Paste your URL and get a full security, performance, and SEO report in under 2 minutes — no signup required.
Run a free scan