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.
"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.
| Where | Best for | Watch out for |
|---|---|---|
A .env file | Local development, a single small server | Keep it out of Git and out of public directories |
| Hosting environment-variable settings (entered in a dashboard) | Production | Limit who can access the dashboard; keep values out of build logs |
| CI (automated test and deploy) secrets | Automation such as GitHub Actions | External tools run in CI can see the values; pass keys with only the rights needed |
| A secrets manager | Several people or several servers | Keep 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.
| Example | OK to publish? | Why |
|---|---|---|
Stripe publishable key (starts with pk_) | Yes | The 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_) | No | They allow server-side operations; the docs recommend restricted keys with narrowed permissions |
Next.js env variable with NEXT_PUBLIC_ | Published | Its 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.
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.
- Revoke or rotate the key in the issuer's dashboard. If the service offers a grace period, end the leaked key "now"
- Set the new key in production and confirm the app works
- Check the issuer's usage history and billing for activity that was not yours
- 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.
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.
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.
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.
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 -1Checking 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
.envright under public - "I'll delete it later", so commit
.envonce - Rotate only the one key you saw abused
The right first step
- App body outside the web root, expose only
public/ - Exclude
.envvia.gitignorefrom 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
- Next.js, "How to use environment variables in Next.js" (16.x) — nextjs.org
- Stripe Docs, "API keys" — docs.stripe.com
- Laravel 13.x, "Configuration" (Environment File Security) — laravel.com
- GitHub Docs, "About push protection" — docs.github.com
- GitGuardian, "The State of Secrets Sprawl 2025" — blog.gitguardian.com
Read next
- After a leak: 543,699 credentials exposed on GitHub are still valid — why you must revoke, not just delete
- The Gyazo breach (September 2026): what leaked, and what users should do today
- Glossary: What is .env · What is a CVE · What is RCE
- Defense: Keep .env off the public web · Next.js CVE hygiene
- Incident: A stolen API key billed for fraud
- Incident: a stolen key got the account banned
- Supply chain: when a single npm install steals your credentials (someone else's code running in the environment where your keys are stored)
FAQ
QWhere should I start with security?
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?
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?
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 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?
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?
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.