Contents

Secrets — database passwords, API keys, payment tokens, encryption keys — must not be stored in code or the repository. The right setup: code contains only variable names, values live in environment variables or a secrets manager, each environment has its own keys, every person and service has the minimum rights needed, and a leaked key can be replaced quickly.

Here is why secrets leak, where to store them, how to handle them in CI/CD and what to do when one leaks.

Why must secrets not be stored in code?

Secrets in code leak along with the code: the repository is copied to developers' laptops, shared with contractors and CI and sometimes — by accident — made public. Even if you delete the file, the key stays in commit history, and bots constantly scan public repositories for such keys.

How secrets leak in practice:

  • a .env file is committed to the repository;
  • a key is pasted into code "temporarily" and forgotten;
  • secrets are sent in a group chat or by email;
  • keys show up in build logs or application errors;
  • a key is embedded in a frontend or mobile app, where it is easy to extract.

For other common vulnerabilities, see OWASP Top 10 explained.

Where should secrets be stored?

Store secrets outside the code — in server environment variables, protected CI/CD settings or a dedicated secrets manager. The choice depends on team size and the number of services.

Method Suits Pros Cons
.env file on the server Small project, one server Simple Manual management, no access log
CI/CD secrets Builds and deployment Built into the platform Tied to one platform
Cloud secrets manager Cloud-hosted projects Permissions, audit, rotation Provider dependency
Self-hosted vault (Vault and similar) Many services, own servers Flexibility, dynamic secrets Needs maintenance
Team password manager People's access to services Convenient, granular sharing Not for machine secrets

An old skeleton key on a light background Photo: Unsplash

How do you handle secrets in development and CI/CD?

In development each programmer has their own test keys, and the repository holds only a template without values. In CI/CD the platform injects secrets during builds and deployments, and they are never printed to logs.

# .env.example — in the repository, no values
DB_PASSWORD=
PAYMENT_API_KEY=
S3_SECRET=

# .gitignore
.env

Rules:

  1. Different keys per environment. Test payment keys in development, live ones only in production.
  2. Least privilege. A file upload key should not grant access to the whole cloud account.
  3. Pre-commit checks. A secret scanner in pre-commit hooks and CI catches keys before they enter history.
  4. Masking in logs. The CI platform and the application never print secret values.
  5. Nothing secret on the client. Anything shipped in a frontend or mobile app is public.

We covered setting up a pipeline in CI/CD with GitHub Actions.

How do you grant access to the team?

Grant access personally and with minimal rights: each person has their own account rather than a shared admin password. Then when an employee or contractor leaves, you disable their access instead of changing every password in the company.

  • separate accounts for people and services;
  • two-factor authentication on every critical system;
  • a list of who has access to what — reviewed regularly;
  • access revoked on the day work with an employee or contractor ends.

More on handing a project between teams in how to switch development vendor.

What should you do if a secret leaks?

If a secret leaks, revoke and replace it immediately — do not just delete it from the repository and hope nobody noticed. Then check the key's usage logs and find out how it leaked so it does not happen again.

Action plan:

  1. Revoke the compromised key and issue a new one.
  2. Update it in every environment and restart services.
  3. Check the provider's logs for suspicious requests made with the key.
  4. If personal data is affected, assess whether you are legally required to notify anyone.
  5. Find the root cause and fix it: scanner, permissions, process.

In short

  • Secrets do not belong in code or repositories, even private ones.
  • Store them in environment variables, CI/CD secrets or a secrets manager.
  • Each environment has its own keys; each service has minimal rights.
  • People's access is personal, with two-factor authentication and regular review.
  • A leaked key is revoked and replaced immediately, then the cause is fixed.

FAQ

  • Can secrets be kept in a private repository?

    No. Every developer and contractor can see a private repository, copies stay on laptops and in CI, and commit history keeps the secret even after the file is deleted.

  • How often should keys be rotated?

    Always when an employee or contractor with access leaves and whenever a leak is suspected. Scheduled rotation of critical keys every few months is convenient once the process is automated.

  • How do you hand access to a new contractor?

    Through a password or secrets manager with separate permissions, not in a messenger. Give the contractor their own accounts with the minimum rights needed so they can simply be disabled when the work ends.