Skip to main content
Security Guides

The .env File Trap: Why Your Next.js Secrets Keep Ending Up in the Browser

SecuriSky TeamApril 14, 202612 min read

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

  • [ ] Use a separate environment file for sensitive data
  • [ ] Load sensitive environment variables only on the server-side
  • [ ] Use the env object to access environment variables in your code
  • [ ] Prefix public environment variables with NEXT_PUBLIC_
  • [ ] Use a security scanner like SecuriSky to detect security issues automatically
  • 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