How to Remove Secrets from Environment Variables and Git History

Quick answer: To remove secrets from environment variables, you must rotate the compromised credentials immediately and use tools like BFG Repo-Cleaner or git filter-repo to scrub them from Git history. Finally, migrate to a dedicated secret manager to prevent plain-text exposure in .env files or system process lists.

By Paula C · Kraftwire Software

· 9 min read

To remove secrets from environment variables, you must first identify the leaked credentials and immediately rotate them, as once a secret is exposed, it is compromised forever. For Git history, use tools like BFG Repo-Cleaner or git filter-repo to scrub the sensitive strings from all commits. Finally, migrate to a dedicated secret manager to ensure no secrets remain in plain-text .env files or process lists.

Why Is It Critical To Remove Secrets From Environment Variables?

Environment variables are often treated as a safe harbor for sensitive data, but they are frequently the source of major data breaches. When secrets like API keys, database passwords, or private certificates are stored in environment variables, they are often accessible to any process running on the host. If an attacker gains limited shell access, they can simply run env or printenv to view every credential your application uses.

Furthermore, environment variables are often logged by crash reporting tools, CI/CD pipelines, and monitoring agents. If a secret is hardcoded into a .env file that accidentally gets committed to version control, it remains in the Git history even if you delete the file in a later commit. Removing these secrets is not just about cleaning up code; it is about reducing the blast radius of a potential compromise.

How To Remove Secrets From Git History Permanently?

Deleting a secret from your current code branch does not remove it from the repository's history. Anyone who clones the repo can checkout an older commit and retrieve the plain-text key. To truly remove secrets, you must rewrite the repository history.

1. Using Git Filter-Repo

The modern standard for scrubbing history is git filter-repo. It is faster and more reliable than the older git filter-branch.

  • Install the tool and run it against your repository.
  • Use the --replace-text flag with a file containing the secrets you want to mask.
  • This will scan every commit, every branch, and every tag to replace the sensitive string with a placeholder.

2. Using BFG Repo-Cleaner

The BFG Repo-Cleaner is a simpler, faster alternative to Git's internal tools. It is specifically designed for removing large files or sensitive strings.

  • Create a passwords.txt file containing the secrets (one per line).
  • Run java -jar bfg.jar --replace-text passwords.txt my-repo.git.
  • After running BFG, you must use git reflog expire and git gc to force Git to delete the old, unreferenced data.

3. Force Pushing Changes

Once the history is rewritten locally, you must force push (git push --force) to the remote server. This will overwrite the history on platforms like GitHub or GitLab. Note that this will disrupt other contributors, so coordinate with your team before performing this action.

How To Avoid Secrets In .env Files During Development?

The most common way secrets leak is through .env files being committed to Git. While no secrets in env vars is the ideal state, many developers still rely on them for local development.

Use .gitignore Properly

Ensure that .env, .env.local, and any variations are explicitly listed in your .gitignore file before you even initialize the repository. You can use a gitignore generator to ensure you are covering all common patterns for your framework.

Provide a Template File

Instead of sharing the actual .env file, create a .env.example file. This file should contain the keys but none of the actual values. This allows other developers to see which variables are required without exposing sensitive data.

Use Env File Linters

Automated tools can check your environment files for common mistakes. An env file linter can detect if you are using insecure formats or if you have accidentally included values that look like production credentials in a development file.

How To Prevent Secrets In Process List Visibility?

On Unix-like systems, the command ps -aux or top can sometimes reveal environment variables passed to a process. If you start a process with MY_SECRET=123 node app.js, that secret might be visible to other users on the same machine.

Avoid Passing Secrets via CLI

Never pass sensitive data as command-line arguments. Arguments are almost always visible in the process list. Instead, have the application read from a file with restricted permissions or a pipe.

Use Filesystem Permissions

If you must use a local file for secrets, ensure it has the strictest possible permissions. Use chmod 600 .env so that only the owner can read or write to the file. You can verify these settings with a chmod calculator.

Use Systemd Secrets or Docker Secrets

If you are deploying in a containerized or orchestrated environment, use the platform's native secret management. Docker Secrets and Kubernetes Secrets mount sensitive data as files in a temporary filesystem (tmpfs) rather than injecting them as standard environment variables, which keeps them out of the global env list.

What Are The Best Practices For Rotating Compromised Keys?

If you find a secret in your Git history or a public environment variable, you must assume it is compromised. Even if you remove it from the history, you cannot be sure who cloned the repo while the secret was live.

1. Invalidate Immediately

Go to the provider (e.g., AWS, Stripe, OpenAI) and revoke the key immediately. Most modern providers allow you to "roll" a key, giving you a 24-hour window where both the old and new keys work, which prevents downtime during the transition.

2. Generate Strong Replacements

When creating new keys, ensure they are cryptographically strong. Use an api key generator or a password generator to create high-entropy strings that are resistant to brute-force attacks.

3. Audit Access Logs

Check the usage logs for the compromised key. Look for any IP addresses or actions that do not align with your application's normal behavior. This helps determine if the leak was actually exploited.

How To Transition To A Dedicated Secret Manager?

The ultimate solution to no secrets in environment variables is to move them into a dedicated Secret Management System (SMS).

Cloud-Native Managers

If you are on AWS, use Secrets Manager or Parameter Store. On Google Cloud, use Secret Manager. These services allow your application to fetch secrets at runtime via an API call using the machine's identity (IAM), meaning no secrets are stored on the disk or in the environment configuration.

Vault Solutions

HashiCorp Vault is the industry standard for platform-agnostic secret management. It provides features like dynamic secrets (generating a database password on the fly that expires after an hour) and detailed audit logs.

Integration with Vibe-Coding Tools

For developers using "vibe-coding" platforms or AI-assisted editors, secret management is even more critical. If you are building with Bolt or Lovable, ensure you are using their built-in environment variable editors rather than hardcoding values into the prompt or the generated files.

How To Audit Your App For Exposed Secrets Automatically?

Manual audits are prone to human error. To ensure that no secrets have slipped through the cracks, you should use automated scanning tools as part of your CI/CD pipeline.

Pre-commit Hooks

Tools like git-secrets or trufflehog can be installed as pre-commit hooks. They scan your staged changes for patterns that look like API keys or private keys and block the commit if anything is found.

External Security Scanners

Using an external scanner provides a "hacker's eye view" of your application. A secret scanner can look for publicly accessible .env files or exposed .git directories on your production server.

SimplyScan for AI-Built Apps

If you are using tools like Cursor, Windsurf, or Replit, the risk of accidental secret exposure is higher because AI often suggests hardcoding values for speed. SimplyScan provides a specialized security scanner that runs 51+ automated checks, specifically looking for exposed API keys and environment variable leaks in vibe-coded applications. It takes about 30 seconds and requires no signup, making it an essential step before any production deployment.

How To Verify Your Environment Is Clean?

After performing a cleanup, you need to verify that the secrets are truly gone and that your application is still functional.

Check the Public Web Root

Ensure that your .env file is not being served by your web server. You can use an exposed files tool to check if common sensitive paths are reachable from the internet.

Verify Headers and Metadata

Sometimes secrets leak through unexpected channels like headers or SEO tags. Use a security headers tool or a meta tags generator to ensure your public-facing metadata is clean and follows best practices.

Monitor for Regressions

Security is not a one-time event. Set up uptime monitoring and regular scans to ensure that a new deployment doesn't accidentally re-introduce a .env file or a hardcoded secret. By integrating security checks into your GitHub or Slack workflow, you can catch leaks the moment they happen.

---

Summary of Remediation Steps:

  • Rotate: Revoke the compromised key and generate a new one.
  • Scrub: Use git filter-repo to remove the string from all Git history.
  • Protect: Add .env to .gitignore and use a gitignore generator.
  • Migrate: Move secrets to a managed service like AWS Secrets Manager or HashiCorp Vault.
  • Scan: Run a SimplyScan report to ensure no other vulnerabilities exist in your vibe-coded app.

By following these steps, you move beyond "security by obscurity" and build a robust architecture where secrets are handled with the programmatic rigor they require. Regardless of whether you are building a simple prototype in Replit or a complex SaaS in V0, keeping secrets out of environment variables is a fundamental pillar of modern web security.

---

FAQ

How do I know if my .env file was pushed to GitHub?

You can check your repository's file list on GitHub, but more importantly, check the commit history. Even if the file isn't in the latest version, it might be in an older commit. Use a secret scanner or search the repository's history for the filename. If found, you must rotate all keys contained in that file immediately.

Can I just delete the commit that contained the secret?

No, simply deleting a commit or "reverting" it creates a new commit that undoes the changes, but the original commit with the secret still exists in the Git database. You must use a tool like BFG Repo-Cleaner or git filter-repo to rewrite the history and physically remove the data from the repository's objects.

Is it safe to use environment variables on Vercel or Netlify?

Platforms like Vercel and Netlify provide a "Settings" UI to input environment variables. This is significantly safer than committing a .env file because the values are encrypted at rest and only injected into the build process. However, you should still ensure these variables aren't accidentally leaked to the frontend code during the build.

What is the difference between a secret and an environment variable?

Environment variables are a mechanism for passing configuration to a program. Secrets are a specific type of configuration that must remain private, such as passwords or keys. While all secrets can be environment variables, not all environment variables (like LOG_LEVEL or PORT) are secrets. The goal is to handle secrets with more care than standard config.

Does SimplyScan detect secrets in my frontend code?

Yes, SimplyScan's automated engine performs checks for exposed API keys and sensitive strings that may have been accidentally bundled into your frontend JavaScript. This is a common issue in AI-built apps where the LLM might hardcode a Supabase service role key or an OpenAI key directly into a React component.

Should I use a .env file for production?

It is generally discouraged to use .env files in production. Most production environments should use a Secret Manager or inject variables directly into the process manager (like systemd or Kubernetes). If you must use a .env file, ensure it is located outside the web root and has restricted filesystem permissions (chmod 600).

Frequently asked questions

How do I know if my .env file was pushed to GitHub?

You can check your repository's file list on GitHub, but more importantly, check the commit history. Even if the file isn't in the latest version, it might be in an older commit. Use a secret scanner or search the repository's history for the filename. If found, you must rotate all keys contained in that file immediately.

Can I just delete the commit that contained the secret?

No, simply deleting a commit or "reverting" it creates a new commit that undoes the changes, but the original commit with the secret still exists in the Git database. You must use a tool like BFG Repo-Cleaner or git filter-repo to rewrite the history and physically remove the data from the repository's objects.

Is it safe to use environment variables on Vercel or Netlify?

Platforms like Vercel and Netlify provide a "Settings" UI to input environment variables. This is significantly safer than committing a .env file because the values are encrypted at rest and only injected into the build process. However, you should still ensure these variables aren't accidentally leaked to the frontend code during the build.

What is the difference between a secret and an environment variable?

Environment variables are a mechanism for passing configuration to a program. Secrets are a specific type of configuration that must remain private, such as passwords or keys. While all secrets can be environment variables, not all environment variables (like LOG_LEVEL or PORT) are secrets. The goal is to handle secrets with more care than standard config.

Does SimplyScan detect secrets in my frontend code?

Yes, SimplyScan's automated engine performs checks for exposed API keys and sensitive strings that may have been accidentally bundled into your frontend JavaScript. This is a common issue in AI-built apps where the LLM might hardcode a Supabase service role key or an OpenAI key directly into a React component.

Should I use a .env file for production?

It is generally discouraged to use .env files in production. Most production environments should use a Secret Manager or inject variables directly into the process manager (like systemd or Kubernetes). If you must use a .env file, ensure it is located outside the web root and has restricted filesystem permissions (chmod 600).

Related guides

  • Environment Variables Security: Stop Leaking Secrets to Production · Environment variables only protect secrets when used correctly. Any variable prefixed VITE_, NEXT_PUBLIC_, or REACT_APP_ is embedded in your JavaScript bundle and readable by every visitor. Keep API keys, service role keys, and database URLs server-side without a public prefix, add .env to .gitignore, and verify your deployed bundle contains no secrets.
  • How to Find Exposed Secrets in Your Code Before They Ship · Exposed secrets hide in three predictable places: frontend bundles, git history, and misprefixed .env files. Grep your code and built output for known prefixes like sk_live_, AKIA, ghp_, and BEGIN PRIVATE KEY, then run an automated secret scanner to catch entropy-based leaks. If you find one, rotate the key first · deleting code does not un-leak it.
  • 60 Free Security & Developer Tools Every Vibe Coder Should Bookmark · Sixty free, no-signup tools cover the security gaps AI app generators leave behind: live checks for SSL, security headers, DNS, CORS, and exposed .env files, browser-local utilities like a JWT debugger and secret scanner, plus generators, converters, and SEO and AI visibility checks. Each takes seconds · run the live checks after every deploy.
  • AES-256 and TLS 1.3 Explained · How Your Data Is Actually Protected · AES-256 encrypts data at rest: stored database files and backups become unreadable ciphertext, with no practical attack demonstrated in 20+ years. TLS 1.3 encrypts data in transit with mandatory forward secrecy and no legacy ciphers. Neither protects application logic · missing access controls and leaked API keys need a security scan.

All security guides · Free security tools · Platform scanners · Security checklist