TL;DR
Your blockchain isn't just storing value — it's storing malware instructions.
Three active campaigns in Q1 2026 — GlassWorm, ForceMemo, and CanisterWorm — are using Solana transaction memos, Internet Computer Protocol (ICP) canisters, and EVM contract state as command-and-control (C2) infrastructure. The blockchain's immutability, which makes it great for trustless finance, also makes it impossible to take down a C2 channel once it's deployed.
If you're building DeFi, running validators, or maintaining npm packages, this is your threat briefing and defense playbook.
Why Blockchain C2 Changes the Threat Model
Traditional malware C2 has a well-known weakness: domains get seized, servers get taken down, IP addresses get blocked. Defenders have decades of playbooks for disrupting C2 infrastructure.
Blockchain C2 inverts this completely:
| Traditional C2 | Blockchain C2 |
|---|---|
| Domains/IPs can be seized | On-chain data is permanent |
| Hosting providers comply with takedowns | No single entity to serve a takedown |
| Defenders can sinkhole domains | Cannot modify or delete transactions |
| Infrastructure costs money to maintain | One transaction fee ≈ $0.00025 on Solana |
| Geographic jurisdiction applies | Globally replicated across thousands of nodes |
The blockchain isn't running the actual C2 — it's a pointer registry. The malware reads an on-chain value (a Solana memo, an EVM storage slot, an ICP canister response), decodes it, and connects to the real C2 server. When defenders block that server, the attacker publishes a new transaction pointing to a fresh endpoint. Cost: fractions of a penny. Time to rotate: seconds.
Campaign 1: GlassWorm — Solana Memos as an Unkillable Dead Drop
Timeline
- October 2025: First observed using invisible Unicode characters to hide malicious code
- Q1 2026: Evolved to encrypted staged loaders; compromised 400+ repos on GitHub, npm, PyPI, VSCode, and OpenVSX
How It Works
GlassWorm's C2 chain follows a precise behavioral sequence:
1. Malware activates (npm postinstall, VSCode extension load, Python import)
2. Queries Solana RPC for transactions from hardcoded wallet address
3. Reads transaction memo field → base64 decode → JSON parse
4. Extracted JSON contains: { "url": "https://c2.example.com/stage2", "key": "..." }
5. Connects to decoded URL, downloads stage 2 payload
6. Stage 2: RAT with keylogging, cookie theft, screenshot capture, proxy relay
The genius is in step 2-4. The Solana memo field was designed for attaching human-readable notes to transactions — "Pizza payment" or "Invoice #1234". GlassWorm repurposes it as a configuration broadcast channel.
What GlassWorm Steals
From DeFi developers specifically:
-
Solana validator keys (typically at
~/.config/solana/id.json) - npm tokens (for publishing malicious package updates)
- GitHub tokens (for the ForceMemo follow-up campaign)
- AWS/GCP/Azure credentials (for cloud-hosted wallets and RPC nodes)
- SSH keys (lateral movement to validators and infrastructure)
The Solana Memo Lookup Pattern
Here's what the malware's Solana query looks like at the RPC level:
{
"jsonrpc": "2.0",
"id": 1,
"method": "getSignaturesForAddress",
"params": [
"ATTACKER_WALLET_ADDRESS",
{ "limit": 1 }
]
}
Followed by getTransaction on the most recent signature, then parsing the memo instruction data. The polling interval is approximately 10 seconds — constant beacon traffic that's detectable if you know what to look for.
Campaign 2: ForceMemo — Weaponizing Stolen GitHub Tokens
ForceMemo is GlassWorm's sequel, using credentials harvested in the first campaign to launch a second wave:
- Stolen GitHub tokens from GlassWorm victims are used to authenticate as legitimate developers
- Hundreds of Python repositories on GitHub are compromised
- Attackers use
git force-pushto rewrite repository history, making injected code appear as if it was always there - Compromised repos contain the same Solana-memo C2 mechanism
Why Force-Push Is Devastating
A normal malicious commit leaves an audit trail — you can see when it was added and by whom. Force-push replaces the commit history entirely. Unless you have an independent snapshot of the repository (a mirror, a CI cache, a local clone), you can't tell the code was changed.
For DeFi teams, this means:
- A dependency you've used for months suddenly contains a Solana-memo C2 backdoor
-
git logshows no new commits -
git diffagainst the remote shows nothing (because the remote is the compromised version) - Your audit of the dependency from last month? It's auditing code that no longer exists on GitHub
Campaign 3: CanisterWorm — ICP Blockchain as Decentralized C2
First Detected: March 20, 2026
Attribution: TeamPCP (same group behind the Trivy compromise)
CanisterWorm takes blockchain C2 a step further by using Internet Computer Protocol (ICP) canisters — essentially smart contracts on the ICP blockchain — as a full C2 server.
Attack Chain
1. Compromised npm publishing tokens (stolen via Trivy supply chain attack)
2. Backdoored patch versions published to every accessible npm package
3. postinstall hook installs Python backdoor
4. Backdoor registered as systemd user service (Linux persistence)
5. Python backdoor polls ICP canister for instructions
6. Canister delivers stage 2 payloads based on victim profiling
Why ICP Canisters Are Worse Than Solana Memos
Solana memos are read-only pointers — they tell the malware where to go. ICP canisters are active compute:
- The canister can profile victims (IP, installed packages, system info) and deliver targeted payloads
- It can implement rate limiting and access control to evade sandbox analysis
- It runs autonomously on the ICP network with no server to seize
- The attacker pays in ICP cycles, which can be pre-funded anonymously
Reported Destructive Capabilities
CanisterWorm payloads observed in the wild include:
- Filesystem wipe logic targeting victims geolocated to specific regions
- Kubernetes cluster deletion commands
- Crypto wallet exfiltration across Solana, Ethereum, and Bitcoin
EVM Chains: The Third C2 Vector
While GlassWorm uses Solana and CanisterWorm uses ICP, EVM-based C2 has been observed in parallel campaigns:
Smart Contract Storage as C2
// Attacker deploys a minimal contract
contract C2Router {
string public endpoint;
function update(string memory _endpoint) external {
require(msg.sender == owner);
endpoint = _endpoint;
}
}
Malware calls endpoint() on the contract, decodes the response, and connects. The attacker calls update() to rotate C2 infrastructure. All of this is:
- Publicly visible on-chain (but so is everything else — hiding in plain sight)
- Immutable once written (old endpoints remain in transaction history)
- Callable from any RPC endpoint worldwide
Proxy Chain Pattern
More sophisticated variants use a router → logic → storage contract chain:
- Malware knows the router address (hardcoded)
- Router points to a logic contract (upgradeable via proxy pattern)
- Logic contract reads from a storage contract
- Any layer can be updated independently
This is the same upgradeable proxy pattern DeFi protocols use — weaponized for malware infrastructure.
Detection: The Read → Decode → Connect Triad
All three campaigns share a detectable behavioral pattern:
[1] Blockchain RPC Read
↓
[2] Decode Pipeline (base64 → JSON → decompress)
↓
[3] First-Seen HTTP(S)/WebSocket Connection
Network Detection Rules
Alert on:
- Non-Web3 hosts making repeated Solana/EVM RPC calls (especially at ~10-second intervals)
- RPC reads followed within seconds by connections to first-seen domains/IPs
- Any CI/CD runner making blockchain RPC calls (this is almost never legitimate)
Endpoint Detection Rules
Alert on:
-
npm postinstallscripts that make network calls to blockchain RPC endpoints - Node.js or Python processes that:
- Call Solana/EVM RPC
- Perform base64 decode or JSON parse on the response
- Immediately make an HTTP(S) connection to the decoded URL
- Creation of systemd user services by npm packages (CanisterWorm persistence)
Solana-Specific IOC Pattern
If you operate Solana RPC nodes, watch for:
- High-frequency
getSignaturesForAddresscalls to the same wallet from non-validator IPs -
getTransactioncalls immediately followinggetSignaturesForAddressfrom the same source - Memo program (
MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr) data in queried transactions containing base64-encoded content
Defense Playbook for DeFi Teams
1. Lock Down CI/CD Blockchain Access
# Example: GitHub Actions network policy
# Block all blockchain RPC from CI runners
- name: Block blockchain RPC in CI
run: |
# Block Solana mainnet RPC
sudo iptables -A OUTPUT -d api.mainnet-beta.solana.com -j DROP
# Block common EVM RPCs
sudo iptables -A OUTPUT -d mainnet.infura.io -j DROP
sudo iptables -A OUTPUT -d eth-mainnet.g.alchemy.com -j DROP
If your CI/CD pipeline doesn't need blockchain access, default-deny it. If it does, route through a monitored proxy.
2. Pin and Verify Dependencies
# Generate lockfile checksums
npm ci --ignore-scripts # Install without running postinstall
sha256sum node_modules/.package-lock.json > lock.sha256
# Verify on subsequent installs
sha256sum -c lock.sha256
Better yet, use --ignore-scripts in CI and run postinstall hooks only for explicitly allowlisted packages.
3. Monitor for Force-Push Attacks
# Set up a git mirror and compare
git clone --mirror https://github.com/org/critical-dep.git /mirrors/critical-dep.git
# Daily check: detect force-push rewrites
cd /mirrors/critical-dep.git
git fetch origin 2>&1 | grep -E "forced update|rejected"
# Compare HEAD against your cached copy
git diff HEAD..origin/main --stat
For critical dependencies, maintain independent mirrors and alert on any history rewrite.
4. Audit Solana Memo Usage
If you're a Solana protocol, monitor memo usage on wallets associated with your team:
// Monitor suspicious memo patterns
const connection = new Connection(clusterApiUrl('mainnet-beta'));
async function checkSuspiciousMemos(walletAddress: string) {
const signatures = await connection.getSignaturesForAddress(
new PublicKey(walletAddress),
{ limit: 50 }
);
for (const sig of signatures) {
const tx = await connection.getTransaction(sig.signature);
const memoInstruction = tx?.transaction.message.instructions.find(
ix => ix.programId.toString() === 'MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr'
);
if (memoInstruction) {
const memoData = memoInstruction.data.toString();
// Flag base64-looking memos
if (/^[A-Za-z0-9+/=]{20,}$/.test(memoData)) {
console.warn(`⚠️ Suspicious base64 memo in tx ${sig.signature}`);
}
}
}
}
5. Wallet/Contract Watchlist Integration
If you identify attacker wallets or contracts:
- Subscribe to on-chain updates for those addresses
- Decode new pointers as they're published
- Preemptively block the decoded C2 endpoints before malware connects
- Share IOCs with your security community
This turns the attacker's transparency against them — every C2 rotation is publicly visible.
6. Developer Workstation Hardening
For anyone with access to validator keys, multisig signers, or deployment keys:
# Audit: Check if any process is making blockchain RPC calls
ss -tnp | grep -E ':8899|:8900|:443' | grep -v expected_processes
# Check for suspicious systemd user services (CanisterWorm persistence)
systemctl --user list-units --type=service --all | grep -v expected_services
# Verify npm global packages haven't been tampered with
npm ls -g --depth=0 2>/dev/null
# Check for unexpected postinstall scripts in dependencies
find node_modules -name "package.json" -exec grep -l "postinstall" {} \;
The Bigger Picture: Why This Matters for DeFi
These campaigns aren't just "malware that happens to target crypto." They represent a fundamental shift in how blockchain infrastructure can be weaponized:
The immutability that protects your protocol's state also protects attacker C2. You can't file a takedown notice with the Solana blockchain.
DeFi developers are high-value targets. A compromised developer with npm publish access, validator keys, or multisig authority is worth more than thousands of regular victims.
Your dependency tree is your attack surface. The average DeFi frontend has 500-1000 npm dependencies. Each one is a potential entry point for GlassWorm or CanisterWorm.
Audit ≠ security. Your smart contracts can be audited 18 times (like Resolv) and still get breached through the development pipeline. Security must cover the entire stack — from developer workstation to deployed contract.
Indicators of Compromise
Known Attacker Patterns
- Solana RPC polling at ~10-second intervals from non-Web3 hosts
- ICP canister queries from npm postinstall hooks
- EVM contract reads followed by immediate HTTP(S) to decoded addresses
-
git force-pushto established repositories with no maintainer explanation - systemd user services created by npm package installation
Detection Heuristic (Pseudocode)
def detect_blockchain_c2(network_events):
for window in sliding_window(network_events, seconds=30):
rpc_reads = [e for e in window if is_blockchain_rpc(e)]
for rpc in rpc_reads:
subsequent = [e for e in window
if e.timestamp > rpc.timestamp
and is_first_seen_destination(e)
and e.source_pid == rpc.source_pid]
if subsequent:
alert(f"Blockchain C2 pattern: {rpc} → {subsequent[0]}")
Key Takeaways
Blockchain C2 is not theoretical. GlassWorm, ForceMemo, and CanisterWorm are active, evolving campaigns targeting your ecosystem right now.
The behavioral triad (RPC read → decode → connect) is your detection anchor. Build alerts around this pattern.
CI/CD is the primary entry point. Lock down blockchain RPC access in build environments. Run
--ignore-scriptsby default.Mirror critical dependencies. Force-push attacks can rewrite history invisibly. Your local cache is your ground truth.
Turn blockchain transparency against attackers. Monitor known wallets/contracts and preemptively block newly published C2 endpoints.
The same properties that make blockchain revolutionary for DeFi — immutability, decentralization, censorship resistance — make it a nightmare when weaponized for malware infrastructure. The arms race is here. Make sure you're not bringing a takedown notice to a blockchain fight.
This research is part of DreamWork Security's ongoing DeFi threat intelligence series. Follow for weekly analysis of vulnerabilities, exploits, and defense patterns across Solana, EVM, and cross-chain ecosystems.
Top comments (0)