T05 · Unauthorized Access and Privilege Escalation
Warning
- Location
- scripts/interact.ts:10
- Finding
- Unconditional Private-Key Loading for Read-Only Commands## Vulnerability Details **File Location**: `scripts/interact.ts:10-18` **Vulnerability Type**: Least-privilege violation involving sensitive signing material **Risk Level**: Medium ### Vulnerable Code ```ts // Load standard solana keypair const keypairPath = path.resolve(os.homedir(), '.config/solana/id.json'); let rawdata; try { rawdata = fs.readFileSync(keypairPath, 'utf-8'); } catch (e) { console.error("Could not find keypair at ~/.config/solana/id.json. Please generate one or configure your environment."); process.exit(1); } const keypair = Keypair.fromSecretKey(new Uint8Array(JSON.parse(rawdata))); ``` ### Technical Analysis The script reads and reconstructs the user's default Solana private key before determining which command will be executed. This behavior applies to transaction-producing commands, but it also applies to operations that do not legitimately require signing authority, including `listen-bounties`, help output, unknown commands, and malformed command invocations. Loading the private key unnecessarily places the secret in the Node.js process memory and exposes it to all code executing in the same process, including imported dependencies, debugging or instrumentation facilities, crash diagnostics, and any compromised runtime component. This violates the principle of least privilege. The code does not directly print or transmit the private key, so exploitation requires another component capable of reading process memory or executing within the Node.js process. ### Attack Path 1. A user invokes a read-only operation such as `npx ts-node interact.ts listen-bounties`. 2. Before dispatching the command, the script reads `~/.config/solana/id.json`. 3. The complete secret key is parsed and reconstructed as a `Keypair`. 4. The secret remains available in process memory for the lifetime of the listener. 5. A compromised dependency, injected debugger, malicious instrumentation hook, or o ...[truncated 785 chars]
- Remediation
- ## Remediation Suggestions - Parse and validate the requested command before accessing any signing material. - Load the keypair only inside commands that actually produce signed transactions: `register-profile`, `publish-bounty`, `claim-bounty`, and `approve-bounty`. - Create a read-only `Connection` for `listen-bounties` rather than constructing an `AnchorProvider` backed by a private key. - Permit an explicit wallet path or secure wallet adapter instead of unconditionally using `~/.config/solana/id.json`. - Minimize key lifetime by constructing the signer immediately before signing and releasing references afterward. - Avoid including secret-containing objects in errors, debug output, telemetry, or crash reports. - Consider hardware-wallet or external signer support so private keys do not need to be loaded directly into the Node.js process.
