T09 · Insecure Skill Coding Practices
Error
- Location
- skills.md:52
- Finding
- Wallet Private Key Created Without Enforced Restrictive Permissions<![CDATA[ ## Vulnerability Details **File Location**: `skills.md:52-62` **Vulnerability Type**: Plaintext sensitive data stored with umask-dependent permissions **Risk Level**: High ### Vulnerable Code ```javascript const wallet = ethers.Wallet.createRandom(); const dir = process.env.HOME + '/.config/impossible_agent'; fs.mkdirSync(dir, { recursive: true }); const file = dir + '/wallet.json'; fs.writeFileSync(file, JSON.stringify({ privateKey: wallet.privateKey, address: wallet.address, publicKey: wallet.publicKey }, null, 2)); console.log('Wallet saved to ' + file); console.log('Address: ' + wallet.address); ``` ### Technical Analysis The generated `wallet.json` contains an unencrypted BSC private key. The creation code does not specify restrictive permissions for either the configuration directory or wallet file. Consequently, their permissions are inherited from the process umask and may allow other local users or processes to read the private key. Although `skills.md:330` later recommends running: ```bash chmod 600 ~/.config/impossible_agent/wallet.json ``` this is advisory rather than enforced by the wallet-generation procedure. The key may therefore remain exposed indefinitely, or during the interval between its creation and the manual permission change. ### Attack Path 1. The user runs the documented wallet-generation script. 2. The script writes an unencrypted private key to `~/.config/impossible_agent/wallet.json`. 3. A permissive process umask causes the directory or file to be readable by another local account or process. 4. The attacker reads and copies the private key. 5. The attacker imports the key into another wallet or signing tool. 6. The attacker signs arbitrary BSC transactions and transfers the wallet's BNB and BEP-20 assets. This path requires local filesystem access under permissions that permit reading the generated file; the code does not itself transmit the private key externally. ### Impact Assessment Disclosure of ...[truncated 491 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions - Create the wallet directory with mode `0700`. - Create the wallet file atomically with mode `0600` rather than relying on a later manual command. - Refuse to use the wallet if ownership or permissions are unsafe. - Prefer an encrypted keystore or operating-system-backed secret store over an unencrypted JSON private key. - Avoid replacing an existing wallet file unless the user explicitly confirms the operation. - Keep the documented recommendation to use a dedicated, low-value wallet. A hardened implementation could use: ```javascript fs.mkdirSync(dir, { recursive: true, mode: 0o700 }); const walletJson = JSON.stringify({ privateKey: wallet.privateKey, address: wallet.address, publicKey: wallet.publicKey }, null, 2); fs.writeFileSync(file, walletJson, { mode: 0o600, flag: 'wx' }); fs.chmodSync(dir, 0o700); fs.chmodSync(file, 0o600); ``` The `wx` flag prevents accidental replacement of an existing wallet. Production use should additionally consider encrypting the private key with a user-supplied secret and minimizing the period for which decrypted key material remains in memory. ]]>
