DEV Community

Cover image for I lost my laptop with every .env file on it. This is the macOS security audit I run now.
Nerd Snipe
Nerd Snipe

Posted on

I lost my laptop with every .env file on it. This is the macOS security audit I run now.

I lost my laptop a few months ago. The hardware was replaceable. The .env files on it were the problem.

Every project I work on lives in a folder on that disk, and nearly every folder had a .env file of environment variables: database URLs with passwords in them, Stripe secret keys, AWS and OpenAI API keys, webhook and OAuth secrets. Whoever had the laptop could have had all of them together, so I treated every key as compromised and rotated the lot. That meant logging into every provider dashboard, updating a shared DATABASE_URL updated in several projects, and redeploys afterwards to confirm nothing broke.

A leaked key gives you no way to tell whether it was already used, which is why rotation is the only real answer. What I could change afterwards was how many places held a readable copy.

How .env files get exposed on a Mac

Theft is the case everyone pictures. The others need no thief.

Physical access covers a lost or stolen Mac, but also a repair shop, a resold machine, or an unencrypted backup drive. What a stranger can read depends on FileVault, your login password, and whether the screen was locked. Past the login screen, one find command lists every .env under your home directory.

On shared Wi-Fi, two things matter. File sharing that's switched on is reachable by other machines on the network. A dev server started with a host flag that binds to all interfaces is reachable too, and a debug route that prints environment variables hands your secrets to whoever asks for it.

Accidental sharing is the everyday version:

  • a .env committed to git, where scanners watch public repos for keys
  • a project folder inside iCloud Drive or a shared Dropbox directory
  • a zip sent to a contractor, dotfiles included
  • a terminal visible during a screen share
  • a config pasted into an AI chat while debugging

Supply chain attacks are the last one. A malicious or compromised package runs with your permissions, and environment files in the working directory are a common target.

All five have the same root cause. The secret is a readable file, so anything that can read the folder can read the secret.

A .env security audit for macOS

Run these on the machine you're on right now.

# every .env file under your home directory
find ~ -name ".env*" -not -path "*/node_modules/*" -not -path "*/.git/*" 2>/dev/null

# is the disk encrypted with FileVault?
fdesetup status

# what is listening on the network, and on which interface?
lsof -iTCP -sTCP:LISTEN -n -P

# has a .env ever been committed to this repo?
git log --all --full-history -- .env
Enter fullscreen mode Exit fullscreen mode

In the lsof output, 127.0.0.1 means local only and * means every interface. Check System Settings under General, Sharing for file sharing and remote login. For any repo where the git command returns a commit, assume the values in that file are public and rotate them, because deleting the file in a later commit leaves it in history.

Moving environment variables into the macOS Keychain

I moved the secrets into KeyStack, a native macOS app for managing environment variables. It stores them in the macOS Keychain instead of in project folders. It unlocks with Touch ID or your password and re-locks when you switch apps. For importing, you point it at a project folder, it finds the .env variants, flags duplicates and previews the result, and you delete the originals afterwards.

A few features matter for this problem specifically. Shared variables belong to several projects at once, so rotating DATABASE_URL is one edit. Each secret can have a rotation interval from 30 to 365 days, and a Needs Rotation filter lists what's overdue. An environment diff shows a key that exists in Development but is missing in Production. An encrypted, password-protected vault backup handles moving to a new Mac.

Dev servers still need a file, so 1.2.0 added activation from the menu bar. I wrote up how self-expiring .env files work from the macOS menu bar in full. Activating a project writes a real .env.local into its folder. The file is deleted when your timeout expires, when the Mac sleeps or the screen locks, or when you deactivate. The menu bar shows a live countdown, and a notification arrives about a minute before deletion.

The tradeoffs are worth knowing. While a project is active the file is plaintext. If KeyStack crashes or the Mac loses power in that window, the file stays until the next launch, when KeyStack removes it. KeyStack doesn't replace FileVault or a strong password. It's single-user and macOS-only, and it can't feed secrets to CI or a production host, so a cloud secrets manager is still the right tool there. It needs no account, makes no network requests, and is a one-time purchase.

KeyStack is on the Mac App Store, and there's more on storing API keys and .env files securely on a Mac.

Top comments (0)