Base64 to YAML
Read the config hiding inside a secret or a variable
Base64 Input
Decoded YAML
Where YAML ends up Base64-encoded
Kubernetes is the usual answer. Every value under data: in a Secret must be Base64, and when the thing being stored is itself a config file you end up with YAML wrapped in Base64 wrapped in YAML. Reading it means peeling a layer, and kubectl get secret x -o jsonpath=... plus a shell pipeline is more ceremony than the question deserves when you just want to know which database host is configured.
Paste the encoded value on the left and the config appears on the right. Nothing is uploaded — which is not a small point given what secrets contain.
One detail this page is deliberate about: the YAML is shown exactly as it was encoded, not re-emitted. That is not laziness. Loading YAML and dumping it again discards every comment, normalises quoting and expands anchors — and in a config file the comments are frequently the most valuable part, since they are where the runbook reference and the "do not change this without talking to networking" warnings live. The document is parsed here only to check that it is valid; the result of that parse is thrown away.
The same encoding shows up outside Kubernetes too: CI systems that only accept single-line variables, Docker's ~/.docker/config.json, and any deployment pipeline where a config file has to survive being passed through a shell. The pattern is always the same — a text file that needs to become one unbroken token, written in the 64-character alphabet RFC 4648 defines so nothing in the path treats any of it as punctuation.
Decoding a value
- Copy the value, not the manifest – From a Secret, take what is to the right of
config.yaml:underdata:— a single Base64 string. Pasting the whole manifest is the most common slip, and the page will tell you if you do. - Read the YAML on the right – Byte for byte as encoded, comments and blank lines included. Long
kubectloutput wrapped across lines is fine — the line breaks are stripped before decoding. - Check the validity note – The decoded text is parsed to confirm it is valid YAML, and any error is reported with a line and column. A tab character used for indentation is the classic one — YAML forbids tabs, and the message is not always obvious about it.
- Do something with it – Copy it, download it, or send it on to YAML to JSON or YAML to Table if you want to compare it against something.
To pull one value out at the terminal: kubectl get secret provisioning-config -o jsonpath='{.data.config\.yaml}' — the backslash matters, because the key contains a dot and JSONPath would otherwise read it as a path separator. Then paste the result here. Note too that a Secret written with stringData: rather than data: is stored unencoded by you and encoded by the API server, so what you wrote and what you read back look different.
One value out of a Secret
On the left, the shape of the manifest — with the part you actually want to copy highlighted. On the right, what comes out. Notice the two comments survive; a tool that parsed and re-dumped the YAML would have silently dropped both, including the one pointing at the rotation runbook.
apiVersion: v1 kind: Secret metadata: name: provisioning-config data: config.yaml: IyBjb25uZWN0aW9uIHNldHRp… # take the VALUE, not the whole file
# connection settings for the provisioning service database: host: pgsql-primary.prod.svc.cluster.local port: 5432 # rotated monthly - see runbook RB-042 user: provisioning_svc features: - esim_provisioning
When you need this
Checking what a running service is actually configured with
The manifest in the repository and the Secret in the cluster drift apart more often than anyone admits — someone patched a value during an incident and never went back. Decoding what is really there settles it in seconds.
Reviewing a change to a sealed or encrypted secret
Tools like Sealed Secrets and SOPS produce diffs nobody can read. Decoding the before and after gives you two plain documents, and JSON Diff compares them properly once YAML to JSON has converted both.
Debugging a CI pipeline that takes config as a variable
When a build system only accepts single-line variables, a YAML config gets encoded to fit. If the job is behaving oddly, the first question is whether the variable holds what you think — and this answers it without echoing a secret into a build log, which you should not do anyway.
Confirming a value was not truncated
Copying a long Base64 string out of a terminal is surprisingly easy to get wrong — a wrapped line missed, a scrollback boundary. If the decoded YAML ends mid-key or fails to parse near the bottom, that is what happened.
What it does
- Comments and formatting survive. The output is the decoded bytes, never a re-dumped document, so nothing is normalised away.
- Wrapped input is fine. Line breaks from terminal output or a manifest are stripped before decoding.
- Validity is checked and located. A YAML error comes with a line and column, corrected to be 1-based — the underlying parser counts from zero, which is a classic off-by-one in error messages.
- Pasting the whole manifest is recognised. Instead of a generic "invalid Base64", the page points out that you want the value from under
data:. - Binary payloads are named. A TLS key or a gzipped archive in a Secret is reported as what it is, with a size, rather than printed as noise.
- Nothing leaves the browser. Necessary for a page whose whole purpose is looking at secrets.
Questions that come up
Are Kubernetes secrets encrypted?
Not by default, and this catches people out. Base64 is encoding, not encryption — the Kubernetes documentation says as much, and anyone who can read the Secret object can read its contents exactly as you just did. Encryption at rest for etcd is a separate thing you have to switch on deliberately, and it does nothing about who can call the API.
Why not reformat the YAML for me?
Because reformatting means loading and re-dumping, and js-yaml — like most YAML libraries — has no way to preserve comments through that round trip. On a config file that is real data loss. Indentation is significant too, so quietly rewriting it is riskier here than in a format where whitespace does not carry meaning.
My decoded YAML has a value that changed type. Is that this page?
No, and it is worth knowing where it comes from. YAML 1.1 parsers read NO as boolean false, so country: NO means Norway to a human and false to PyYAML. The YAML 1.2 core schema narrowed booleans to true and false, which is why Node and Python can disagree about the same file. Nothing is rewritten here — the text you see is the text that was encoded — but the trap is real once the config reaches your application. The write-up on YAML gotchas goes through it.
The output says it is not valid YAML.
Look first for a tab character used for indentation, which YAML forbids outright and which arrives easily via a copy from an editor set to tabs. After that, an unquoted value containing a colon followed by a space, which the parser reads as a nested key. Both are reported with a line number.
Can I go the other way?
YAML to Base64 encodes, which is what you want when writing a Secret by hand. For other payloads, Base64 to JSON and Base64 to Text.
Related tools
Worth reading
- Kubernetes: Secrets – Including the paragraph explaining that Secrets are not encrypted by default
- The YAML 1.2.2 specification – The core schema section is where the boolean rules changed from 1.1