Skip to content

fix(secret): keep piped multi-line secrets and mask them - #489

Merged
jahvon merged 3 commits into
mainfrom
fix/piped-secret-input
Oct 13, 2026
Merged

jahvon merged 3 commits into
mainfrom
fix/piped-secret-input

Conversation

@jahvon

@jahvon jahvon commented Oct 13, 2026

Copy link
Copy Markdown
Member

Summary

flow secret set NAME with the value piped on stdin kept only the first line, so a PEM key or JSON credential was silently truncated. The piped-input summary also printed the masked value in plaintext, so echo "$SECRET" | flow secret set NAME wrote the secret to stdout, where a CI log or an agent transcript would capture it. Both came from how tuikit's form reads piped input, and are fixed there.

Notable Changes

  • Bump tuikit to v0.5.1. A lone masked field reads stdin to EOF and keeps multi-line input byte for byte; the summary prints masked values as ********. Confirm and text prompts still read one line, so yes | flow vault remove X or a stdin held open by a parent process does not block.
  • Bump vault to v0.4.1.
  • The secret set value field is required, so an empty pipe fails instead of storing an empty secret.

Fixes #478

Bump tuikit to v0.5.1 and vault to v0.4.1. tuikit now reads a lone
masked field to EOF, so `printf 'a\nb\n' | flow secret set NAME`
stores the value byte for byte instead of its first line, and the
piped-input summary prints the value as a mask instead of plaintext.

The secret value field is now required, so an empty pipe fails instead
of storing an empty secret.

Fixes #478
@jahvon

jahvon commented Oct 13, 2026

Copy link
Copy Markdown
Member Author

Verification

  • flow validate passed locally (generate, lint 0 issues, unit + e2e, schemas). It ran against the tuikit commit that is now tagged v0.5.1.
  • Built binary, piped into an unencrypted vault:
    • printf 'line1\nline2\n' | flow secret set pem → secret get --plaintext -o json returns "line1\nline2\n"
    • summary prints ********, never the value
    • printf '' | flow secret set empty → exit 1, required field with key 'value' not set
    • echo secret-x | flow secret set one → stored as secret-x (trimmed, unchanged behavior)
  • New e2e specs cover the multi-line round trip, no echo, and the empty pipe.
  • Not verified: the interactive (TTY) prompt by hand. With Required: true, an empty interactive submit should now be rejected rather than stored.

Worth a close look

  • tuikit v0.5.0 alone regressed single-field confirm prompts: they read stdin to EOF, so the existing vault remove / secret remove e2e specs (which never close their pipe) took 120s each, unblocked only by GC finalizing the writer. v0.5.1 limits read-to-EOF to multiline fields and a lone masked field. The secrets e2e container is back to ~0.5s.
  • tests/secret_cmds_e2e_test.go: the new BeforeAll resets the test IO after vault create, because output from a second in-process command in the same spec isn't captured by the harness. That's a pre-existing harness quirk I worked around rather than fixed.

Out of scope (follow-up)

  • Masking secretRef values in run output at capture time. It needs per-run secret state plumbed from env resolution to the output writers in internal/services/run.

@codecov

codecov Bot commented Oct 13, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

The multiline value prompt now reads stdin to EOF, so a pipe left open
blocked the spec until GC closed the writer, about 120s later.
@jahvon

jahvon commented Oct 13, 2026

Copy link
Copy Markdown
Member Author

Follow-up: the cache set e2e spec piped its value without closing the pipe. Its prompt is a multiline field, which correctly reads to EOF, so the spec blocked ~120s until GC closed the writer. Closing the pipe in the spec fixes it. Full e2e on this branch now runs in 6.0s (was ~184s); slowest spec 0.54s. lint 0 issues.

@jahvon
jahvon merged commit 4933228 into main Oct 13, 2026
23 checks passed
@jahvon
jahvon deleted the fix/piped-secret-input branch October 13, 2026 05:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

secret set: piped stdin keeps only the first line

1 participant