Skip to content
>_ITDITDWeb Security Platform

Security Guides

Security basics: what's actually dangerous about .env and API keys

A first step for indie developers who keep hearing 'security matters' but don't know where to start. What .env is, what happens when an API key leaks (with a flow diagram), and the minimum four habits you can do today — explained plainly, without fear, hands-on.

Published 2026-06-07 Updated 2026-10-06 8 min read

"I keep hearing security matters, but where do I even start?" This is the very first step for indie developers. Not to scare you — only things you can act on today, in order.

Why start with secrets (.env and API keys)

Most real incidents begin not with sophisticated attacks but with a leaked secret. The two cases this site is built on were both secret leaks:

Protect your secrets and you prevent most common incidents. So we start here.

What .env is (in 30 seconds)

.env is a file that gathers your app's secret values: the database password, external API keys, the key that encrypts sessions. Because the secrets sit together in one file, a leak exposes all of them at once — so it's the file to guard first (→ Glossary: What is .env).

Where secrets can live (.env, environment variables, secrets managers)

.env is not the only place for secrets. Choose by scale and use.

WhereBest forWatch out for
A .env fileLocal development, a single small serverKeep it out of Git and out of public directories
Hosting environment-variable settings (entered in a dashboard)ProductionLimit who can access the dashboard; keep values out of build logs
CI (automated test and deploy) secretsAutomation such as GitHub ActionsExternal tools run in CI can see the values; pass keys with only the rights needed
A secrets managerSeveral people or several serversKeep read access minimal and rotate regularly

For CI secrets, the 2021 Codecov incident is a useful reference. An external tool run in CI was tampered with, and secrets held in CI environment variables were taken (→ the Codecov incident).

Keys you may publish and keys you must not

Some API keys are meant to ship inside browsers or mobile apps; others are for servers only. Assume anything sent to a browser can be read by anyone.

ExampleOK to publish?Why
Stripe publishable key (starts with pk_)YesThe docs say it can be included in front-end code; it cannot perform sensitive operations such as creating charges
Stripe secret key (sk_) or restricted key (rk_)NoThey allow server-side operations; the docs recommend restricted keys with narrowed permissions
Next.js env variable with NEXT_PUBLIC_PublishedIts value is inlined into browser JavaScript at build time
Next.js env variable without NEXT_PUBLIC_Not published (server only)Put secret values here

When unsure, check the service's official docs for whether the key may be used client-side. If they do not say, treat it as a key you must not publish.

What an API key leak means

An API key is "a string that lets a service treat the caller as you." In the wrong hands, the damage spreads like this.

① The API key leaks (public dir, git commit, or via a vulnerability)
↓ on a delay (days+)
② A third party uses the external service "as you"
↓
③ Fraudulent billing / data read-write / impersonation
Quiet at first. Abused on a delay — then one day a bill or breach surfaces.

Stolen keys are often resold and abused on a delay — "nothing happens at first, then a surprise bill" is the classic pattern. So "after you notice" is too late; the point is to not leak them in the first place.

What to do if a key may have leaked

Deleting the key from your code does not stop it. GitGuardian's 2025 report found that 70% of secrets leaked in public repositories in 2022 were still valid at the time of the report. Respond in this order.

  1. Revoke or rotate the key in the issuer's dashboard. If the service offers a grace period, end the leaked key "now"
  2. Set the new key in production and confirm the app works
  3. Check the issuer's usage history and billing for activity that was not yours
  4. Removing it from files and Git history can wait until after revocation (deleting alone does not stop anyone who already has a copy)

Details are in 540,000 credentials published on GitHub are still valid. GitHub turns on "push protection" by default, which stops a personal account from pushing secrets to a public repository, but it does not catch every kind of secret.

Four habits to start today

Nothing hard. Just these four.

1

Don't expose it

Never place .env or the app body in a web-visible directory (the web root). Expose only public/. Concrete steps for shared hosting: this guide.

2

Don't commit it

Add .env* to .gitignore (allow !.env.example); share only a value-less example. Once committed it's recoverable from history, so keep it out from the start.

3

Rotate everything if leaked

Not just one key — rotate every secret that could have leaked. Order: external API / OAuth → encryption keys → mail → DB. Act as if seen.

4

Self-check

Occasionally confirm /.env can't be opened from the outside (below).

Self-check (only against domains you own)

# A 200 with a body means it's exposed. 403/404 is okay for now.
curl -sI https://your-domain/.env | head -1
curl -sI https://your-domain/.git/config | head -1

Checking this on every deploy catches placement mistakes early.

Besides what is visible from outside, check Git and your build output too (run in your own repository).

# Was .env ever committed? (any output means it was, at some point)
git log --all --oneline -- .env
# env-like files Git tracks now (anything other than .env.example needs a look)
git ls-files | grep -i "env"

To confirm no key ships to the browser, search your build output folder (for Next.js, .next/static) for the first few characters of the key. You can also paste code into the secret leak scanner before publishing (nothing is sent anywhere).

Common mistakes vs the right first step

Common

  • "It works", so drop .env right under public
  • "I'll delete it later", so commit .env once
  • Rotate only the one key you saw abused

The right first step

  • App body outside the web root, expose only public/
  • Exclude .env via .gitignore from the start
  • If it leaks, rotate every secret in the env

Next steps

From here, the next topics are "the risky defaults in your stack" and "a system to not fall behind on published CVEs." No rush, one at a time.

Sources

FAQ

QWhere should I start with security?
A

With not leaking your secrets (.env and API keys). Most real incidents start there. Don't expose them, don't commit them to git, rotate everything if they leak, and self-check occasionally — that prevents the majority.

QWhat concretely happens if an API key leaks?
A

Someone can act as you against an external service. The common outcomes are fraudulent billing (heavy usage charged to you) and reading/writing your data. Stolen keys are often resold and abused on a delay.

QCan I put .env in git?
A

No. Add .env* to .gitignore and share only a value-less .env.example. Once committed, it can be recovered from git history even after you delete it later.

QWhat is a .env file?
A

A text file that keeps an app's settings, especially secret values such as passwords and API keys, separate from the code. Each line is NAME=value. Many frameworks, including Laravel, Next.js, and Django, read it at startup. Because the secrets sit together, it must stay out of Git and out of public directories.

QWhat is the difference between .env and environment variables?
A

Environment variables are the mechanism itself: values the OS or runtime passes to a program. A .env file is a container that holds those values in a file so the app or a library can load them as environment variables at startup. In production, many setups skip the .env file and pass environment variables from the hosting dashboard or a secrets manager instead.

QIs it OK to put an API key in front-end (browser) code?
A

Only if the key is explicitly documented as safe to publish. Anyone can read the JavaScript you send to the browser. For example, Stripe's documentation says publishable keys (starting with pk_) can be included in front-end code, while secret keys (sk_) and restricted keys (rk_) must not be exposed. In Next.js, environment variables prefixed with NEXT_PUBLIC_ are inlined into browser code, so never give a secret that prefix.