Skip to content

fix(cli): pay no longer accepts the secret key as a CLI argument - #108

Merged
Eras256 merged 1 commit into
mainfrom
fix/104-pay-secret-argv-leak
Oct 9, 2026
Merged

Eras256 merged 1 commit into
mainfrom
fix/104-pay-secret-argv-leak

Conversation

@Eras256

@Eras256 Eras256 commented Oct 9, 2026

Copy link
Copy Markdown
Collaborator

Closes #104.

The leak

nirium pay <url> --secret S... put a real Stellar signing key where two
things could read it that have nothing to do with the user running the
command: the shell's history file, and ps's full command line view —
argv is visible to any other process/user on the same machine by
design, not a Nirium-specific gap.

The fix

Removed -s, --secret <secret> from the pay command entirely. The key
now resolves, in order:

  1. NIRIUM_SECRET_KEY environment variable (already existed, never
    touches argv).
  2. nirium config set secretKey S... (already existed, same reason).
  3. A new interactive prompt, only when neither of the above is set and
    stdin is a real terminal — readline with its own echo suppressed, so
    the key is never printed, not even as asterisks (which would still
    leak its length).

--json mode is for scripts, not a human typing at a keyboard, so it
never prompts — missing key there fails immediately with the same clear
error it always gave, just without mentioning a flag that no longer
exists.

Also updated the two other spots that told people to use --secret:
serve's own "test this server" hint, and the README's usage example +
options table.

Verified by hand (no test harness exists yet — #103)

  • nirium pay --help no longer lists --secret.
  • NIRIUM_SECRET_KEY=S... nirium pay <url> --json resolves the key and
    proceeds (reaches the network call) without prompting.
  • nirium pay <url> --json with nothing set fails clean, exit 1, no
    hang — doesn't try to read a terminal that isn't there.

🤖 Generated with Claude Code

`nirium pay ... --secret S...` put a real signing key in the shell
history file and in `ps`'s full command line, readable by anyone else on
the machine — true for any process, argv is not private. Removed the
`-s, --secret` option entirely.

The key now resolves from NIRIUM_SECRET_KEY, the config store
(`nirium config set secretKey S...`), both already-existing paths that
never touch argv, or a new interactive prompt when neither is set and
stdin is a real terminal: readline with its echo suppressed, so nothing
typed reaches the screen or any log capturing it. `--json` mode (meant
for scripts, not a human at a keyboard) never prompts — it fails with
the same clear error instead.

Updated the two other places that told people to use the removed flag:
`serve`'s own "test this server" hint, and the README's usage example
and options table.

No automated test added — packages/cli has no test runner wired up yet
(#103). Verified by hand: --secret is gone from --help, NIRIUM_SECRET_KEY
resolves without prompting, and --json with no key set fails clean
(exit 1, no hang) instead of trying to read a terminal that isn't there.

Closes #104

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@Eras256
Eras256 merged commit 51782b2 into main Oct 9, 2026
@Eras256
Eras256 deleted the fix/104-pay-secret-argv-leak branch October 9, 2026 06:06
Eras256 added a commit that referenced this pull request Oct 11, 2026
`nirium config set secretKey <key>`, `config set facilitatorApiKey <key>`
and `serve --api-key <key>` all put a credential in shell history and in
`ps`. They now exit 1, save or use nothing, and say why. The values come
from the environment (NIRIUM_SECRET_KEY / FACILITATOR_API_KEY), a hidden
prompt on a terminal, or stdin when there is none. Same reasoning as #108.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
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.

nirium pay --secret leaks the signing key into shell history and the process list

1 participant