Relationships
#406 Warn when a ${{ }} secret expression is single-quoted in a command/shell run: script
Opened by magistr · 5/21/2026· Shipped 5/21/2026
Problem
${{ vault.get(vault, KEY) }} used inside a command/shell model's methods.execute.arguments.run script does not inline the plaintext. It compiles to a shell env-var reference "${__SWAMP_VAULT_N}" and injects the real secret as env var __SWAMP_VAULT_N. This is great — secrets stay out of the script text and logs.
But it has a silent footgun. If the author wraps the expression in single quotes — the natural, defensive shell habit for assigning a literal value that might contain special characters — the shell never expands the reference. The variable silently becomes the literal 20-char string "${__SWAMP_VAULT_0}" instead of the secret. There is no error or warning at validate, eval, or run time.
It's especially insidious because symmetric uses mask it: e.g. a model that both creates a credential and verifies it will use the placeholder on both sides, so it appears to "work" — until a different consumer (a .env file, another tool, a server restart) needs the real value and fails.
Real-world cost: I traced a multi-hour MongoDB auth failure to exactly this. MPW='${{ vault.get(...) }}' created a DB user whose password was the literal placeholder "${__SWAMP_VAULT_0}"; auth then worked from the creating model but failed everywhere else.
Reproduction
swamp vault put v K=AAAAAAAAAABBBBBBBBBBCCCCCCCCCCDDDDDDDDDDEEEEEEEEEE # 50 charscommand/shell run::
S='${{ vault.get(v, K) }}' # single quotes
D="${{ vault.get(v, K) }}" # double quotes
printf 'single=%s double=%s\n' "${#S}" "${#D}"→ single=20 double=50. (od -c of the single-quoted value shows "${__SWAMP_VAULT_0}".) vault read-secret and --input both return the correct 50.
Proposed improvement
At validate/eval time, statically detect a ${{ … }} expression enclosed in single quotes within a command/shell run: field and emit a warning (ideally a validation error), e.g.:
secret/expression inside single quotes will not be expanded by the shell — use double quotes:
"${{ ... }}"
Alternatives / additions:
- Make the injected placeholder fail loud if unexpanded (resolve to empty or a sentinel that breaks obviously) rather than a plausible literal token.
- Document the double-quote requirement prominently in the command/shell + vault docs.
Impact
A low-effort lint that prevents a subtle, time-consuming, and security-relevant class of secret-handling mistakes.
Environment
- swamp CLI: 20260513.132340.0-sha.a0faa6ea
Shipped
Click a lifecycle step above to view its details.