Skip to content

Redesign write command: make it interactive to not leak secret into bash history - #303

Merged
jadrol merged 1 commit into
masterfrom
feature/INFRA-1251/write-command-without-leaking-secret
Aug 12, 2026
Merged

Redesign write command: make it interactive to not leak secret into bash history#303
jadrol merged 1 commit into
masterfrom
feature/INFRA-1251/write-command-without-leaking-secret

Conversation

@jadrol

@jadrol jadrol commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Requestor/Issue: @jadrol
Risk (low/med/high): low
Tested (yes/no): yes, locally
Description/Why:

Old syntax for write command made us leak secret into bash history which with connection to internal security tooling made us leak secrets.

Rewrote write command to be interactive, secret is not being printed at any time, no leak to history.

> ./treasury write development/httpbingo/JAREK_TEST
Please paste your secret:
Success! Data written to: development/httpbingo/JAREK_TEST (7 characters)

There is still posibility to pass secret via pipe, see bats for examples.

@jadrol
jadrol requested a review from a team as a code owner August 11, 2026 09:39
@jadrol
jadrol requested review from GabiBia and lgd-michallasisz and a lite review from Copilot August 11, 2026 09:39
@jadrol jadrol self-assigned this Aug 11, 2026
@jadrol
jadrol force-pushed the feature/INFRA-1251/write-command-without-leaking-secret branch from bec6fbc to 6669afe Compare August 11, 2026 09:44

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR redesigns the treasury write CLI to avoid leaking secrets via command-line arguments (shell history / process list) by reading secrets interactively (TTY) or via stdin (CI/scripts), and updates docs/tests accordingly.

Changes:

  • Make write accept only the key argument and read the secret from TTY (hidden) or stdin; add shared secret-input helper + unit tests.
  • Update Bats + README usage examples to reflect the interactive/stdin-based workflow and new output format.
  • Improve SSM backend initialization by loading ambient AWS SDK config when a caller did not provide a usable aws.Config.

Reviewed changes

Copilot reviewed 8 out of 9 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
cmd/write.go Switches write to interactive/stdin secret input and updates help text + output formatting.
cmd/secret_input.go Adds logic for securely reading secrets from TTY (hidden) or stdin (piped) with newline trimming + validation.
cmd/secret_input_test.go Adds unit coverage for stdin trimming/validation behavior and edge cases.
test/bats/tests.bats Updates integration tests to pass secrets via stdin pipe and adds negative/edge test cases.
README.md Documents interactive write behavior and safe scripting patterns.
backend/backend.go Adjusts SSM backend to load default AWS SDK config when not provided by caller.
backend/backend_test.go Adds test coverage for caller-provided AWS config scenario.
go.mod / go.sum Adds golang.org/x/term dependency for hidden TTY input.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread cmd/secret_input.go
}

func readSecretFromTerminal(cmd *cobra.Command, file *os.File) (string, error) {
out := cmd.OutOrStdout()
Comment thread cmd/write.go
Comment on lines +32 to +34
The secret value is never given as a command line argument, so it does not end
up in the shell history nor in the process list. When run in a terminal treasury
asks for the secret and hides what is typed, otherwise the secret is read from
Comment thread backend/backend.go
Comment on lines +42 to +46
awsConfig := options.AWSConfig
if !isConfigured(awsConfig) {
var err error
awsConfig, err = config.LoadDefaultConfig(context.Background(), config.WithRegion(options.Region))
if err != nil {
Copilot AI review requested due to automatic review settings August 11, 2026 09:44

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 8 out of 9 changed files in this pull request and generated no new comments.

Suppressed comments (3)

cmd/secret_input.go:42

  • The interactive prompt is written to stdout via cmd.OutOrStdout(). If the user redirects stdout (e.g. treasury write key > out.txt), they won’t see the prompt and it will pollute machine-readable output. Interactive prompts should go to stderr while the success message stays on stdout.
	out := cmd.OutOrStdout()

	_, _ = fmt.Fprint(out, secretPrompt)
	//nolint:gosec // G115: a file descriptor always fits in an int
	secret, err := term.ReadPassword(int(file.Fd()))

README.md:134

  • This documentation claims printf '%s\n' "${SECRET}" can be used when the secret must end with a newline, but stdin input always has a single trailing EOL stripped (see trimEOL/readSecret tests). As written, this printf example would still lose the final newline.
The single trailing newline that `echo` adds is stripped, so there is no need for `echo -n` (which is not portable between shells anyway). Any other whitespace is treated as a part of the secret. If the secret has to end with a newline, use `printf '%s\n' "${SECRET}"` or write it from a file with `--file`.

backend/backend.go:46

  • When options.Region is empty, calling config.LoadDefaultConfig(..., config.WithRegion(options.Region)) risks overriding an ambient region from env/shared config with an empty value, which can later cause "missing region" errors at runtime. Only apply config.WithRegion when Region is explicitly set.
		awsConfig := options.AWSConfig
		if !isConfigured(awsConfig) {
			var err error
			awsConfig, err = config.LoadDefaultConfig(context.Background(), config.WithRegion(options.Region))
			if err != nil {

@jadrol
jadrol merged commit fde8184 into master Aug 12, 2026
7 checks passed
@jadrol
jadrol deleted the feature/INFRA-1251/write-command-without-leaking-secret branch August 12, 2026 06:19
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.

3 participants