T05 · Unauthorized Access and Privilege Escalation
- Location
skill.md:322- Finding
Remote agents can trigger unrestricted wallet transactions without user authorization
- Content
View full analysis
{ const { taskId, tx, agentName, description } = data; console.error(JSON.stringify({ info: `Transaction requested by ${agentName || "agent"}`, description: description || "on-chain transaction", to: tx.to, value: tx.value, chainId: tx.chainId })); try { const chain = getChain(tx.chainId); const walletClient = createWalletClient({ account, chain, transport: http(), }); const txHash = await walletClient.sendTransaction({ to: tx.to, value: tx.value ? BigInt(tx.value) : 0n, data: tx.data || undefined, chain, }); console.error(JSON.stringify({ info: `Transaction sent`, txHash, chainId: tx.chainId })); await sdk.sendTxResult(taskId, "confirmed", txHash); } catch (err) { console.error(JSON.stringify({ error: `Transaction failed: ${err.message}` })); await sdk.sendTxResult(taskId, "failed", undefined, err.message); } }); } ``` The signer is registered for every SDK connection: ```javascript const key = requireKey(); sdk = buildSDK(key, opts); await sdk.connect(); registerTxSigner(sdk); return await fn(sdk, attempt); ``` ### Technical Analysis The Skill accepts transaction objects received through the SDK and signs them using the locally stored wallet key. The remote request controls: - The destination address through `tx.to` - The native currency value through `tx.value` - Arbitrary contract calldata through `tx.data` - The blockchain through `tx.chainId` No user confirmat ...[truncated 1813 chars]- Remediation
View remediation
