Helm
Kubernetes
Sensitive Data
DevOps
Security Practices

How to pass sensitive data to helm values file that is committed?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

If a Helm values file is committed to Git, it should not contain plaintext secrets. The safe pattern is to keep committed values files non-sensitive and inject the real secret material through encrypted files, an external secret manager, or pre-created Kubernetes Secret objects referenced by the chart.

Do Not Commit Plaintext Secrets

The most important point is simple: a committed values.yaml file is configuration, not a safe secret store.

This is risky even in private repositories because:

  • repository access is broader than production secret access
  • old commits preserve leaked values
  • forks, logs, and CI artifacts can spread the data further
  • rotation becomes harder once the value is in Git history

So the first answer is negative: do not put the actual sensitive value into the committed file unless it is encrypted before commit.

A Better Pattern: Commit Secret References, Not Secret Values

A strong chart design uses values that point to an existing Kubernetes secret instead of embedding the raw secret itself.

Committed values file:

yaml
1app:
2  existingSecret: my-app-secret
3  usernameKey: username
4  passwordKey: password

Template snippet:

yaml
1env:
2  - name: APP_USERNAME
3    valueFrom:
4      secretKeyRef:
5        name: {{ .Values.app.existingSecret }}
6        key: {{ .Values.app.usernameKey }}
7  - name: APP_PASSWORD
8    valueFrom:
9      secretKeyRef:
10        name: {{ .Values.app.existingSecret }}
11        key: {{ .Values.app.passwordKey }}

Now the committed file contains only a reference, while the actual secret is created out of band.

Inject Sensitive Values at Deploy Time

If the chart really must receive a secret value directly, inject it at deployment time rather than storing it in Git.

For example:

bash
helm upgrade --install my-app ./chart   --set-string app.password="$APP_PASSWORD"

Or use a separate uncommitted override file in CI:

bash
helm upgrade --install my-app ./chart -f values.yaml -f values.secret.yaml

That still requires good CI secret handling, but it avoids leaving the value in the repository.

Use Encryption If Secret Files Must Be Versioned

Sometimes teams need secret material in version control for workflow reasons. In that case, commit only encrypted secret files, not plaintext values.

The exact tooling can vary, but the principle stays the same:

  • keep encrypted data in Git
  • decrypt only in trusted deployment workflows
  • never commit the plaintext output

This is the only reasonable interpretation of “commit a values file with sensitive data” in a security-conscious setup.

Prefer External Secret Systems When Possible

A stronger long-term design is to let Kubernetes consume secrets from an external manager or operator-driven secret source. Then Helm deploys references and policies rather than raw credentials.

That approach is often better for:

  • credential rotation
  • auditability
  • least-privilege access
  • separation of deployment config from secret ownership

It is more infrastructure upfront, but it scales better than passing raw secrets through more and more Helm layers.

Common Pitfalls

The biggest mistake is base64-encoding a secret and treating that as protection. Base64 is only an encoding, not encryption.

Another issue is using --set or --set-string carelessly in local shells where command history, process listings, or CI logs may expose the value.

Developers also sometimes commit a secret once, rotate the live credential, and forget that the original secret is still permanently present in Git history.

Finally, charts that require raw secret values in the main committed values.yaml are usually designed too rigidly. Prefer secret references or externalized secret injection.

Summary

  • Do not commit plaintext secrets in Helm values files.
  • Prefer committed values that reference pre-created Kubernetes secrets.
  • Inject sensitive values at deploy time if direct values are unavoidable.
  • If secret files must live in Git, store only encrypted versions.
  • Design charts so secret handling is separate from ordinary committed configuration.

Course illustration
Course illustration

All Rights Reserved.