How to Securely Manage API Keys and Secrets in Code

Security2026-09-15TryQuickToolBox

You commit your code, push to GitHub, and move on. Days later you discover your API key was scraped from a public repository and used to rack up thousands of dollars in cloud bills. This is not a rare edge case; it is one of the most common and costly security mistakes in modern development. Hardcoded secrets in source code are a gift to attackers, and they are surprisingly easy to avoid.

Why Hardcoded Secrets Are So Dangerous

When you embed an API key, database password, or private token directly in your code, you lose control over who can see it. Source code travels: it gets cloned, forked, copied into Docker images, pasted into chat apps, and sometimes published accidentally. Once a secret is in version control, it lives forever in the Git history, even if you delete it in a later commit.

Attackers actively scan public repositories for patterns that look like keys. Automated bots can find and exploit a leaked key within minutes. Even in private repositories, hardcoded secrets violate the principle of least privilege: every developer with read access automatically gets production credentials.

Rule #1: Never Hardcode Secrets

This sounds obvious, but it is the foundation. The first step is to remove any secret from your source files. This includes not just obvious strings like sk_live_... but also connection strings, private keys, and webhook signing secrets.

Instead, your code should read secrets from the environment at runtime. Here is a simple example in Python:

import os

api_key = os.environ.get("PAYMENT_API_KEY")
if not api_key:
    raise RuntimeError("PAYMENT_API_KEY is not set")

In Node.js, you would use process.env.PAYMENT_API_KEY. In Go, os.Getenv("PAYMENT_API_KEY"). The pattern is universal: the code expects the secret to be provided externally.

Using Environment Variables Safely

Environment variables are a big improvement, but they are not a silver bullet. They can leak through error reports, debug logs, or process listings. Follow these practices:

For local development, libraries like python-dotenv or dotenv for Node.js make it easy to load a .env file without hardcoding anything. Just remember: that file must never be committed.

Centralized Secret Managers for Production

Environment variables work well for small projects, but they become unwieldy when you have many services, multiple environments, and a need for auditing. A dedicated secret manager solves these problems by storing secrets encrypted at rest, controlling access with fine-grained policies, and providing an audit trail.

Popular options include:

Your application fetches secrets from the manager at startup or on demand, often using an SDK. This decouples secret storage from code and lets you rotate credentials without redeploying.

Secrets in CI/CD Pipelines

Your build and deployment pipelines also need secrets, such as registry passwords or deployment tokens. Most CI systems (GitHub Actions, GitLab CI, CircleCI) provide encrypted secret storage. Use those features instead of putting secrets in pipeline configuration files.

For example, in GitHub Actions you define secrets in the repository settings and reference them like this:

steps:
  - name: Deploy
    run: ./deploy.sh
    env:
      API_TOKEN: ${{ secrets.DEPLOY_API_TOKEN }}

Be careful with pull requests from forks: secrets are not passed to workflows triggered by fork PRs by default, which is good. Never echo secrets in logs; mask them if your CI system supports it.

Rotate Secrets Regularly

Even with perfect storage, secrets can leak through other channels: a compromised laptop, a misconfigured logging service, or a departing employee. Rotation limits the window of exposure.

Set a rotation schedule based on sensitivity. High-value keys (payment gateways, admin APIs) might rotate every 30–90 days. Lower-risk keys can rotate less often. Automate rotation where possible: AWS Secrets Manager and Vault can rotate database credentials automatically.

When rotating, ensure your application can handle multiple valid secrets during the transition. A common pattern is to accept both the old and new secret for a short period, then deactivate the old one.

Detect and Prevent Leaks

Prevention is better than cure, but detection is your safety net. Use pre-commit hooks to scan for secrets before they are committed. Tools like git-secrets, trufflehog, or gitleaks can catch accidental commits.

Also enable secret scanning on your Git hosting platform (GitHub, GitLab, Bitbucket all offer this). If a secret does slip through, revoke it immediately and rotate. Deleting the commit is not enough; assume the secret is compromised the moment it touches a remote repository.

Comparison of Secret Storage Approaches

Method Best For Risks
Environment variables Small apps, local dev Leak via logs, process inspection
.env files Local development Accidental commit, no encryption
Secret managers Production, teams Complexity, added dependency
CI/CD secret stores Build and deploy pipelines Limited to pipeline scope

FAQ

Can I store secrets in a private repository?

No. Private repositories still have many users and integrations with read access. Secrets can leak through forks, CI logs, or a compromised account. Always use environment variables or a secret manager, even for private code.

What should I do if I accidentally commit a secret?

Revoke and rotate the secret immediately. Simply deleting the commit or rewriting history is not enough because the secret may already be cached or cloned. Treat it as compromised and replace it.

Are environment variables secure enough for production?

They are better than hardcoding but not ideal for large-scale production. Environment variables can be exposed in crash dumps, debugging endpoints, or process listings. For production, use a dedicated secret manager with access controls and auditing.

When you need to quickly format or validate JSON configuration files that contain non-sensitive settings, the JSON Formatter can help you spot syntax errors before they break your deployment. Remember: never paste actual secrets into online tools.