Free — no signup required

Secrets Management: Beyond Environment Variables

2 min read

The Problem with Environment Variables

Environment variables are the most common way to pass secrets into CI jobs, but they have significant weaknesses:

  • Visible in process listings: On a shared machine, ps aux or /proc/<pid>/environ can expose environment variables to other processes.
  • Logged accidentally: A misconfigured step that runs env or printenv dumps all secrets to the build log.
  • Inherited by child processes: Every subprocess spawned by the CI job inherits all environment variables, including secrets it doesn't need.
  • No audit trail: There is no record of which jobs accessed which secrets, or when.

Secrets Managers: The Right Tool

A dedicated secrets manager stores secrets encrypted at rest, controls access with fine-grained policies, provides an audit log of every access, and supports automatic rotation.

HashiCorp Vault

Vault is the most widely deployed open-source secrets manager. It stores secrets encrypted, issues dynamic credentials (e.g., generating a new database password for each CI job that expires after the job), and logs every read. A CI job authenticates to it with a short-lived token (itself issued via OIDC or AppRole auth) and reads out just the specific secret value it needs.

AWS Secrets Manager

AWS Secrets Manager integrates natively with IAM. If your pipeline uses OIDC federation (as covered above), it can fetch secrets from Secrets Manager without any additional credentials — the OIDC-assumed role simply needs read permission on the specific secret, and the job queries it directly by name.

Masking Secrets in Logs

Even with a secrets manager, secrets sometimes end up in environment variables temporarily. CI platforms provide log masking — they scan build output and replace known secret values with ***.

In GitHub Actions, any value stored in ${{ secrets.* }} is automatically masked. For dynamically fetched secrets — like a value just pulled from Secrets Manager mid-job — you must register them manually with a special masking command before they're written anywhere else, so any later step that echoes them shows *** instead of the real value in the log.

Interview Tip

Interviewers often ask: "How do you prevent secrets from appearing in CI logs?" The answer has layers: (1) use a secrets manager rather than hardcoding in environment variables, (2) use the CI platform's native masking (::add-mask:: in GitHub Actions), (3) audit your pipeline steps to ensure no step runs env, printenv, or echoes variables directly, and (4) configure log retention policies so old logs containing accidentally leaked secrets are purged. Mentioning all four layers signals a defense-in-depth mindset.

This is one of 18 chapters

Every chapter is free — Kubernetes, Terraform, SRE, distributed systems, and more — with fast daily review built in.

Sign up free