T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/superhero-wallet.mjs:19
- Finding
- Wallet Private Keys Are Exposed Through Process Arguments, Standard Output, and Plaintext Shell Configuration<![CDATA[ ## Vulnerability Details **File Location**: `scripts/superhero-wallet.mjs:19-25`, `scripts/superhero-wallet.mjs:53-63`, `SKILL.md:65-84`, `guides/setup.md:21-40` **Vulnerability Type**: Sensitive credential exposure through command-line arguments, terminal output, and plaintext persistence **Risk Level**: High ### Vulnerable Code `scripts/superhero-wallet.mjs:19-25`: ```js function generateWallet() { const account = MemoryAccount.generate(); console.log(JSON.stringify({ success: true, address: account.address, AE_PRIVATE_KEY: account.secretKey, next_step: `export AE_PRIVATE_KEY=${account.secretKey}`, warning: 'Save this private key securely. Back it up offline. Never commit it to git.', })); } ``` `scripts/superhero-wallet.mjs:53-63`: ```js function importWallet(secretKey) { if (!secretKey) { console.error('Usage: node scripts/superhero-wallet.mjs import <secretKey>'); process.exit(1); } const account = new MemoryAccount(secretKey); console.log(JSON.stringify({ success: true, address: account.address, next_step: `export AE_PRIVATE_KEY=${secretKey}`, warning: 'Save this private key securely. Back it up offline. Never commit it to git.', })); } ``` `guides/setup.md:21-40`: ```bash node {baseDir}/scripts/superhero-wallet.mjs generate ``` This outputs a new `AE_PRIVATE_KEY` and `address`. Set the environment variable before running any other script: ```bash export AE_PRIVATE_KEY=<your_secret_key> ``` For persistence across sessions, add it to `~/.zshenv` or `~/.profile` (never commit this to git). ```bash node {baseDir}/scripts/superhero-wallet.mjs import "<secret_key>" ``` ### Technical Analysis The wallet import interface accepts a private key as a positional command-line argument. Command-line arguments can be exposed through shell history, process inspection facilities, terminal recording, audit systems, job runners, and agent execution transcripts. Both wallet generation and w ...[truncated 2833 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. **Remove command-line private-key import** - Do not accept private keys through `process.argv`. - Read an existing key from a hidden interactive TTY prompt, a protected file descriptor, or a dedicated secret manager. - Ensure interactive input disables terminal echo. - Reject secret-bearing positional arguments to prevent accidental legacy use. 2. **Stop emitting secrets through standard output** - Return only non-sensitive information such as the public wallet address and setup status. - Do not include the private key in JSON, `next_step`, errors, debugging output, or agent-readable terminal results. - Ensure exception handlers and SDK debugging modes cannot serialize the account object. 3. **Use secure wallet storage or an external signer** - Prefer an OS keychain, hardware wallet, encrypted keystore, or wallet service that signs transactions without disclosing raw key material. - Apply restrictive filesystem permissions if an encrypted keystore is used. - Keep decryption credentials separate from the encrypted wallet file. 4. **Replace plaintext shell-profile persistence** - Remove instructions to write the private key to `~/.profile`, `~/.zshenv`, `~/.bash_profile`, or similar files. - Document secure secret injection through the agent platform or a trusted secret manager. - If environment variables remain supported for compatibility, clearly warn that inherited process environments may be readable and recommend a dedicated low-balance wallet. 5. **Harden wallet generation** - Require an explicit, local, secure interactive workflow before revealing a newly generated recovery secret. - Display it only through a channel excluded from agent transcripts and centralized logging. - Require confirmation that the user stored the recovery material securely before discarding it from memory. - Never duplicate the secret in multiple output fields. 6. **Rotate exposed credentials ...[truncated 322 chars]
