T09 · Insecure Skill Coding Practices
- Location
skills.md:54- Finding
Plaintext Wallet Private Key Created Without Explicit Restrictive Permissions
- Content
View full analysis
Vulnerability Details
File Location:
skills.md, lines 54–65
Vulnerability Type: Plaintext secret storage with permissions dependent on the process umask
Risk Level: HighVulnerable Code Snippet:
javascript const fs = require('fs'); const path = require('path'); const { ethers } = require('ethers'); const wallet = ethers.Wallet.createRandom(); const dir = process.env.HOME + '/.config/bsc_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));Technical Analysis
The wallet-generation instructions store a BSC private key in plaintext using
fs.writeFileSyncwithout explicitly setting the file mode. The resulting permissions therefore depend on the runtime environment's umask. Although line 341 later recommends runningchmod 600, that recommendation is separate from the creation command and is not automatically enforced.On a system with an insufficiently restrictive umask, the wallet file may remain readable by other local users or processes. The file directly contains the signing key for the wallet, so confidentiality of the file is the principal access-control boundary protecting all assets held by the wallet.
The Skill legitimately requires access to a signing key to perform its declared trading functionality. However, creating the key in plaintext without enforcing restrictive permissions does not apply the minimum protection necessary for that functionality.
Attack Path
- The user or agent runs the documented wallet-generation command under a permissive umask.
~/.config/bsc_agent/wallet.jsonis created without an explicit0600mode.- The separate
chmod 600security recommendation is omitted or delayed. - Another local user, compromised process, or co-tenant reads
wallet.json.
...[truncated 806 chars]
- Remediation
View remediation
Remediation Suggestions
- Create
~/.config/bsc_agentwith mode0700. - Create the wallet file atomically with mode
0600, rather than relying on the ambient umask or a later manual command. - Refuse to load an existing wallet file if it is owned by another user, is a symbolic link, or has group/other permissions.
- Avoid overwriting an existing wallet unless the user explicitly authorizes key replacement.
- Prefer an encrypted keystore, hardware-backed signer, operating-system key store, or isolated signing service instead of storing a raw private key.
- Never print, log, return, or transmit the private key.
Example hardened creation pattern:
javascript const fs = require('fs'); const path = require('path'); const { ethers } = require('ethers'); const wallet = ethers.Wallet.createRandom(); const dir = path.join(process.env.HOME, '.config', 'bsc_agent'); const file = path.join(dir, 'wallet.json'); fs.mkdirSync(dir, { recursive: true, mode: 0o700 }); fs.writeFileSync( file, JSON.stringify({ privateKey: wallet.privateKey, address: wallet.address, publicKey: wallet.publicKey }, null, 2), { mode: 0o600, flag: 'wx' } );The implementation should additionally verify ownership and effective permissions after creation.
- Create
