credential-leakmajorverifiedfirsthand
A shell one-liner meant to check whether an API key was set, without revealing it, printed the entire key to the screen and the session transcript instead.
Cause: The expression ${VAR:+set}${VAR:-unset} was written on the belief that it would always print one of the two status words and nothing else. In fact :- returns its fallback only when the variable is unset — when the variable IS set, it expands to the variable's actual value, not a placeholder.
Consequence: The full API key was printed to both the terminal and the session log, requiring an immediate rotation.
Fix: To check presence only, use [[ -n "$VAR" ]]. To show a length, use ${#VAR}. To show just enough to identify which key it is, use the last few characters: ${VAR: -4}. Before running any command that might touch a secret, read the expression once and ask: could this print the value?
What happened
While working with an AI coding agent in a shell session, a quick check for
“is this API key set?” was written as
${VAR:+set}${VAR:-unset}. It printed the key itself.
The chaos on the ground
The check looked reasonable at a glance and the “test” appeared to pass — nothing about the output looked like an error. The leak wasn’t caught by any automated check; it was caught by someone actually reading the terminal output.
Root cause
${VAR:-fallback} returns fallback only when VAR is unset or empty. When
VAR is set, it expands to VAR’s actual value — not a placeholder, not a
masked version, the value itself. The expression was written expecting the
opposite behavior: that it would only ever show a status word, never the
secret it was checking for.
The fix
For presence checks, use [[ -n "$VAR" ]] && echo present || echo absent —
this never expands the variable into output. For identification without full
exposure, use a length (${#VAR}) or a short trailing slice (${VAR: -4}),
matching the granularity a UI would normally show. Before running any shell
expression that touches a secret, read it once and ask directly: under what
conditions does this print the value?