DEV Community

ohmygod
ohmygod

Posted on

ForceMemo: How Stolen Credentials Turned Hundreds of GitHub Python Repos Into Blockchain-Powered Malware Distributors

If you thought the GlassWorm campaign was bad, its sequel is worse. ForceMemo — first reported by StepSecurity on March 18, 2026 — is an active supply-chain attack that has silently backdoored hundreds of Python repositories across GitHub. The malware uses Git's force-push to rewrite history, making injections invisible to anyone who doesn't know exactly where to look, and leverages the Solana blockchain as an uncensorable command-and-control channel.

This isn't theoretical. It's happening right now, with new repos being compromised daily.


From Credential Theft to Mass Compromise

ForceMemo is the direct downstream consequence of GlassWorm, the earlier campaign that spread through malicious VS Code and Cursor extensions. GlassWorm's Stage 3 payload includes a dedicated credential harvesting module that steals GitHub tokens from:

  • git credential fill (system credential manager)
  • VS Code extension storage databases
  • ~/.git-credentials (plaintext credential file)
  • The GITHUB_TOKEN environment variable

Once ForceMemo operators have these tokens, they don't just compromise one repository per victim — they hit every repo on the account. User BierOne had 6 repositories compromised. The organization wecode-bootcamp-korea lost 6. HydroRoll-Team lost 6. The pattern is clear: one credential leak, total developer account wipeout.

Targeted project types: Django apps, Flask APIs, ML research code, Streamlit dashboards, and pip-installable packages. If it's Python and it's on GitHub, it's a target.


The Stealth Technique: Force-Push History Rewriting

This is what makes ForceMemo genuinely terrifying. Instead of creating pull requests or adding new commits (which would appear in activity feeds and notification emails), the attacker:

  1. Takes the latest legitimate commit on the repo's default branch
  2. Rebases it, appending obfuscated malware to a key Python file (setup.py, main.py, app.py)
  3. Force-pushes the modified commit back to the default branch

The result: the commit message, author name, and author date are identical to the original. There's no new commit in the log. No pull request. No notification. The GitHub UI looks completely unchanged.

The Only Fingerprints

Two subtle indicators betray the attack:

1. Committer date vs. author date mismatch

# Legitimate author date preserved:
Author Date: 2017-04-24

# But the committer date reveals the actual injection:
Committer Date: 2026-03-10

# That's a 9-year gap on amirasaran/request_validator
Enter fullscreen mode Exit fullscreen mode

StepSecurity found gaps ranging from 33 days to 9 years across compromised repositories.

2. The "null" committer email

Across hundreds of malicious commits, the committer email is consistently set to the string "null" — a fingerprint of the attacker's tooling. This is your most reliable detection signal.

GitHub Events API Evidence

The force-push is visible in the Events API, which preserves the before and after commit SHAs:

{
  "type": "PushEvent",
  "actor": "amirasaran",
  "created_at": "2026-03-10T21:58:02Z",
  "ref": "refs/heads/master",
  "before": "260ca635...",  // clean commit (legitimate PR merge)
  "after":  "17849e1b..."   // malicious rebased commit
}
Enter fullscreen mode Exit fullscreen mode

Anyone running pip install from the after commit gets owned.


The Payload: Three-Layer Obfuscation + Solana C2

Obfuscation Layers

The injected code is appended to the end of legitimate Python files. It uses three layers:

# Layer 1: Base64 decode
# Layer 2: Zlib decompress  
# Layer 3: XOR decrypt (key: 134)

# Marker variable (identical across ALL compromised repos):
lzcdrtfxyqiplpd = '<4,800-character base64 blob>'
Enter fullscreen mode Exit fullscreen mode

The variable name lzcdrtfxyqiplpd is the universal indicator. Search for it:
GitHub Code Search: lzcdrtfxyqiplpd

CIS Exclusion Check

Before executing, the malware checks locale, timezone, and UTC offset. If the system is Russian, it exits. This is a well-documented pattern in Eastern European cybercrime — don't attack domestic systems.

The deobfuscated source contains Russian comments:

# "Эмуляция объекта Buffer из Node.js" 
#  (Emulation of Node.js Buffer object)
# "Получение подписей для адреса Solana"
#  (Getting signatures for Solana address)
Enter fullscreen mode Exit fullscreen mode

Solana Blockchain as C2

Instead of a traditional C2 domain (which can be seized or sinkholed), ForceMemo reads instructions from Solana transaction memos:

C2 Wallet: BjVeAjPrSKFiingBn4vZvghsGj9KCE8AJVtbc9S8o8SC

Active since: November 27, 2025

The malware queries this wallet via 9 fallback RPC endpoints:

Endpoint Purpose
api.mainnet-beta.solana.com Primary Solana RPC
solana-mainnet.gateway.tatum.io Tatum gateway
go.getblock.us GetBlock
solana-rpc.publicnode.com Public node
api.blockeden.xyz BlockEden
solana.drpc.org dRPC
solana.leorpc.com Leo RPC
solana.api.onfinality.io OnFinality
solana.api.pocket.network Pocket Network

Why this matters: The attacker can update the payload URL at any time by posting a new Solana transaction. The instructions are immutable and censorship-resistant. You can't take down a blockchain memo.

The Final Stage

Once the C2 memo is read, the malware:

  1. Downloads Node.js v22.9.0 from nodejs.org (cross-platform: Windows/macOS/Linux, x64/ARM)
  2. Fetches an AES-encrypted JavaScript payload from the URL in the memo
  3. Decrypts and executes using the downloaded Node.js runtime
  4. Creates ~/init.json with a 2-day timer to prevent repeated execution

The final payload harvests SSH keys, GitHub tokens, cryptocurrency wallet data, and installs remote access tooling.


Why DeFi Developers Should Care

This isn't just a "Python security" story. The overlap with the crypto ecosystem is direct:

1. Your dev environment IS your wallet. If you develop DeFi protocols, your machine likely has private keys, deployment scripts, .env files with RPC credentials, and wallet seed phrases. ForceMemo's final payload targets all of these.

2. Solana validator operators at risk. Anyone running Solana infrastructure who installs Python tooling from GitHub is a potential victim. Validator keys have direct financial value.

3. Smart contract audit firms. Auditors frequently clone and build client repositories. A compromised setup.py in a client's dependency could backdoor the auditor's machine.

4. CI/CD pipelines. GitHub Actions workflows that run pip install from Git repos (rather than PyPI) execute setup.py automatically. The malware runs in your CI environment with access to whatever secrets are available.


Detection Checklist

For Individual Developers

  • [ ] Search your cloned repos for the marker: grep -r "lzcdrtfxyqiplpd" ~/
  • [ ] Check for ~/init.json — its presence means the payload already ran
  • [ ] Look for ~/node-v22.9.0-* folders — the malware's Node.js runtime
  • [ ] Review your Git credential storage: cat ~/.git-credentials
  • [ ] Check VS Code extensions for anything unfamiliar installed recently
  • [ ] Rotate GitHub tokens immediately if you used any Cursor/VS Code extension from an untrusted source

For Repository Maintainers

# Check for committer date vs author date mismatches:
git log --format='%H | Author: %ai | Committer: %ci | Email: %ce' -5

# Look for "null" committer email:
git log --format='%ce' | grep -i "null"

# Compare current HEAD with last known good commit:
git diff <known-good-sha> HEAD
Enter fullscreen mode Exit fullscreen mode

For CI/CD Pipelines

  • Pin dependencies to specific commit SHAs, not branches
  • Use pip install from PyPI (not raw GitHub repos) wherever possible
  • Enable StepSecurity Harden-Runner or equivalent network monitoring
  • Monitor for unexpected outbound connections to Solana RPC endpoints

Mitigation: Git Configuration Hardening

Prevent force-push attacks on your repos:

# Require signed commits on protected branches
# (GitHub Settings → Branches → Branch protection rules)

# Enable branch protection:
# ✅ Require pull request reviews before merging
# ✅ Require signed commits
# ✅ Do not allow force pushes
# ✅ Do not allow deletions

# For organizations, enforce at the org level:
# Settings → Code security → Push protection
Enter fullscreen mode Exit fullscreen mode

Credential hygiene:

# Use SSH keys instead of stored tokens
# If you must use tokens, scope them minimally:
# - repo:status (read-only) 
# - NOT repo (full access)

# Never store tokens in plaintext:
# Bad:  ~/.git-credentials
# Good: git credential-store with OS keychain

# Rotate tokens regularly:
gh auth refresh
Enter fullscreen mode Exit fullscreen mode

Timeline

Date Event
Nov 27, 2025 Solana C2 wallet first active
Jan–Mar 2026 GlassWorm campaign steals developer credentials
Mar 8, 2026 Earliest confirmed ForceMemo injection
Mar 10, 2026 django-restful-admin force-push detected
Mar 13, 2026 Multiple ML research repos compromised
Mar 18, 2026 StepSecurity publishes initial report
Mar 20, 2026 Campaign still active, new repos being hit

The Bigger Picture: Blockchain Infrastructure as Attack Surface

ForceMemo, GlassWorm, and Windsurf IDE attacks all share a common thread: Solana's permissionless transaction memo system is being systematically weaponized as C2 infrastructure. The same property that makes blockchain censorship-resistant makes it an ideal dead drop for malware operators.

This creates an uncomfortable tension for the Solana ecosystem. The protocol works exactly as designed — anyone can post a memo to the blockchain, and it persists forever. But "working as designed" doesn't mean "working as intended" when the design enables uncensorable malware infrastructure.

The DeFi security community needs to reckon with this. Blocking specific RPC endpoints is a game of whack-a-mole (the malware already uses 9 fallbacks). The real solutions lie in:

  1. Developer environment isolation — Don't develop DeFi on the same machine where you store keys
  2. Supply chain verification — Pin, hash, verify everything you install
  3. Credential compartmentalization — No single token should give access to everything
  4. Runtime monitoring — Catch the payload phone-home even if you miss the injection

The supply chain is only as strong as its weakest credential. In 2026, that credential is probably sitting in a VS Code extension database on a developer's laptop.


This article is part of the DeFi Security Research series. Follow for weekly deep dives into smart contract vulnerabilities, audit methodologies, and DeFi security tooling.

References:

Top comments (0)