API-279: Guard wallet export against accidental plaintext key disclosure - #501
API-279: Guard wallet export against accidental plaintext key disclosure#501gulshngill wants to merge 2 commits into
Conversation
wallet export is now redacted by default (addresses only, no decryption). Printing private keys requires explicit acknowledgement via --reveal, which warns on stderr when stdout is an interactive terminal. New --file <path> writes keys to an exclusively-created 0600 file (refusing to overwrite, cleaning up partial writes) while keeping stdout clean. Tests prove key material never reaches ordinary errors, DEBUG logs, or telemetry payloads. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
| // (key-free, but noisy) reaches the envelope. | ||
| let fd; | ||
| try { | ||
| fd = fs.openSync(options.file, 'wx', 0o600); |
There was a problem hiding this comment.
Potential file inclusion attack via reading file - medium severity
If an attacker can control the input leading into the ReadFile function, they might be able to read sensitive files and launch further attacks with that information.
Show fix
Remediation: Ignore this issue only after you've verified or sanitized the input going into this function. This issue is only relevant in the backend, not in the frontend!
Reply @AikidoSec ignore: [REASON] to ignore this issue.
More info
pr-reviewer Summary for #82a93e2📝 2 findings Review completed. Please address the findings below. Findings by Severity
Review effort: 3/5 (Moderate) SummaryThis is a well-considered security improvement. The three-mode export design (redacted default / Findings (2 medium)
|
|
@nansen-pr-reviewer re-review |
Summary
nansen wallet export <name>previously printed raw EVM and Solana private keys to stdout with only a warning line. This PR gates plaintext disclosure behind explicit acknowledgement and adds a safer file-based export path.wallet export <name>now prints addresses +[REDACTED]placeholders and never decrypts — no password needed, secrets never materialize in memory on the default path.--reveal(explicit acknowledgement): prints plaintext keys to stdout, exactly as before. When stdout is an interactive terminal, a warning goes to stderr first (scrollback/screen-share/terminal-logging risk). Works fully non-interactively —NANSEN_WALLET_PASSWORD=... nansen wallet export <name> --revealis the automation path.--file <path>(safer path): writes the export JSON to an exclusively-created file with 0600 permissions. Refuses to overwrite (O_EXCL, which also defeats pre-planted symlinks), removes the file if a mid-write/close failure leaves partial key material, and keeps stdout free of secrets.--reveal+--filetogether, bare--file, and non-string--filevalues are rejected before any decryption.revealjoins the boolean-flag allowlist inparseArgsso no argument ordering can make it swallow the wallet name or bypass the--fileconflict check.DEBUG=1stderr output, or telemetry payloads (which carry flag names and error codes only). Includes an ENOSPC mid-write test asserting the partial file is removed.skills/nansen-wallet-managerdocuments the three modes;skills/nansen-wallet-keychain-migrationverification steps now use--revealwith all output discarded, branching on the exit code (the old bare-export check would have become a silent false positive).Breaking-ish: scripts that parsed
wallet exportoutput must add--revealor switch to--file. Shipped as aminorchangeset with a migration note. Wallet generation, storage format, and signing are untouched, per the ticket.Explicit assumptions
--revealflag rather than an interactive confirm — this repo forbids interactive prompts in core, and a flag serves humans and agents identically.Validation
npm test: 54 files, 2048 passed (17 new), all mockednpm run lint: clean--file, error/causeleakage, telemetry/DEBUG surfaces all traced clean)Linear: API-279
🤖 Generated with Claude Code