Secure CLI private-key delivery through an inherited file descriptor#2337
Draft
zachlendon wants to merge 6 commits into
Draft
Secure CLI private-key delivery through an inherited file descriptor#2337zachlendon wants to merge 6 commits into
zachlendon wants to merge 6 commits into
Conversation
Add --private-key-fd <FD> to buzz-cli as a secure alternative to --private-key/BUZZ_PRIVATE_KEY, letting a parent process (e.g. Personal Delegate) hand off the Nostr private key over an inherited file descriptor instead of argv or the environment. - clap conflicts_with makes --private-key-fd mutually exclusive with --private-key and BUZZ_PRIVATE_KEY resolution; FD is bounded to [3, 1024]. - Reads at most 256 bytes from /dev/fd/<FD> via safe Rust (no FromRawFd/unsafe), rejecting empty/oversized/non-UTF8 input with sanitized errors that never include key content. - Key material (from either source) is wrapped in zeroize::Zeroizing end-to-end, including the raw byte buffer on fd-mode error paths. - BUZZ_PRIVATE_KEY is explicitly cleared from the process environment in fd mode as defense-in-depth against procfs/ps environ inspection. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
--help rendered the live BUZZ_PRIVATE_KEY value inline via clap's [env: ...] annotation, leaking the secret to anyone who ran `buzz --help` with the key set. Set hide_env_values on --private-key so help still documents the BUZZ_PRIVATE_KEY env var name but never prints its value. Add a subprocess-based regression test that spawns the built buzz binary with a synthetic BUZZ_PRIVATE_KEY in the child env and asserts --help/-h output never contains it. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Closes the original inherited fd via nix::unistd::close — opening /dev/fd/<fd> only duplicates the descriptor, so the original leaked for the process lifetime otherwise. Zeroizes the read buffer from before the first read attempt so a partial-read I/O failure can't leave unscrubbed key bytes behind. Drops the parsed key string immediately after Keys::parse succeeds instead of letting it live across the rest of the async command. Removes a dead env::remove_var call made unreachable by clap's conflicts_with on --private-key/--private-key-fd.
Replace the ad hoc serde_json::json! macro with derived Serialize structs for the buzz capabilities output, and rename cmd_capabilities to cmd_show to match the pack.rs dispatch naming convention. Adds contract tests asserting the exact schema/field values and that supported tracks cfg!(unix). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What changed
Adds a secure inherited-file-descriptor path for supplying the Buzz private key to CLI operations used by deterministic adapters.
--private-key-fdon UnixBUZZ_PRIVATE_KEYvalue from appearing in help outputbuzz capabilitiesresponse so callers can fail closed on incomplete buildsWhy
The Personal Delegate must sign Buzz relay operations without placing a Nostr private key in argv, environment variables, logs, prompts, or receipts. The adapter also pins the exact executable digest and checks this capability contract before resolving the key.
Validation
No live relay, user key, or credential was used.