
GlassWorm didn’t stop at VS Code extensions. Three months after the original campaign hijacked developer IDEs to harvest credentials, the same threat actor ran a second phase called ForceMemo — using the stolen GitHub tokens to quietly backdoor more than 400 Python repositories with malicious force-pushes designed to be invisible to a normal git log. The C2 infrastructure was taken down in May. The infected repos are not.
What ForceMemo Is
ForceMemo is the evolved form of the GlassWorm supply chain attack. Where GlassWorm’s first phase compromised developer machines through malicious VS Code and Cursor extensions, the second phase weaponized the tokens those extensions stole. Starting March 8, 2026, the attackers used harvested GitHub personal access tokens to push obfuscated malware into the default branches of hundreds of Python projects — Django apps, machine learning repositories, Streamlit dashboards, and PyPI packages.
StepSecurity, Aikido, Socket, and the OpenSourceMalware community identified 433 compromised components in total. The combination of GitHub repos, npm packages, and VS Code extensions made this one of the broadest developer-targeting supply chain attacks on record.
The Force-Push Trick That Hides Everything
This attack is harder to catch than a typical supply chain compromise. The attacker doesn’t just add a new commit — they take the latest legitimate commit on your default branch, append the obfuscated malware payload to a file like setup.py, main.py, or app.py, and force-push while preserving the original commit message, author name, and author date. What you see in git log looks exactly like it always did.
There is one tell. The committer date doesn’t match the author date — sometimes by months, sometimes by years. And across many of the malicious commits, the committer email is set to the string null. That’s the fingerprint of the attacker’s tooling, identified in StepSecurity’s detailed forensic analysis.
The injected code itself is layered: base64 decoding, zlib decompression, XOR encryption with key 134, randomized variable names, and invisible Unicode characters woven into the file. Searching for the string lzcdrtfxyqiplpd in your Python files is the fastest single-pass check for compromise — it’s a marker variable present in every injection.
The Solana C2: Why This Pattern Doesn’t Go Away
Once executed, the malware queries a Solana blockchain wallet for its command-and-control instructions. It reads transaction memo fields from the wallet address BjVeAjPrSKFiingBn4vZvghsGj9KCE8AJVtbc9S8o8SC and decodes base64 URLs pointing to the next payload, cycling through nine different Solana RPC endpoints for resilience.
This matters because blockchain memos are immutable. When CrowdStrike, Google, and the Shadowserver Foundation disrupted GlassWorm’s C2 infrastructure on May 26, 2026, they took down the traditional servers and the BitTorrent DHT channels. The Solana records remain. The final payload is a full-featured infostealer: keylogger, cookie and session token harvester, screenshot capture, SSH key theft, and a fake Chrome extension that targets crypto wallets.
Who Should Check Right Now
If you maintain a Python project on GitHub, clone Python repos frequently, or have ever used pip install git+https://github.com/... to install directly from a repository, you’re in the affected population. The attack concentrated on Django applications, ML research code, Streamlit dashboards, and PyPI packages.
You’re especially exposed if you installed or updated any VS Code or Cursor extension between October 2025 and March 2026 — that’s how GlassWorm harvested the tokens used in the ForceMemo phase.
How to Check Your Repositories
Run these checks against any Python repo you maintain or recently cloned:
# Look for the null committer fingerprint in recent commits
git log --format="%H %ae %ce" | grep " null$"
# Search for the marker variable in Python source files
grep -r "lzcdrtfxyqiplpd" .
# Check for persistence artifacts on your machine
ls ~/init.json 2>/dev/null && echo "COMPROMISED: init.json found"
ls ~/node-v22.9.0 2>/dev/null && echo "WARNING: suspicious node folder found"
If lzcdrtfxyqiplpd appears in any file, or if your git log shows commits from a null committer, treat your repository and the machine you run it on as compromised.
What to Do If You’re Hit
Don’t just delete the malicious commit. The full remediation sequence:
- Revoke all GitHub personal access tokens immediately. Go to GitHub Settings → Developer settings → Personal access tokens → delete everything. Regenerate with fine-grained, short-lived tokens.
- Find the last clean commit before March 8, 2026, and force-push it to overwrite the malicious history on your default branch.
- Rotate all secrets. SSH keys,
.envfiles, cloud credentials, API keys — anything on the compromised machine is burned. - Notify users and collaborators who may have installed from your repo between March and May 2026.
- Enable branch protection now. In GitHub repo settings, require pull requests for the default branch and disable force-pushes. This attack only works against repos where maintainers can push directly.
If you executed malicious code — whether from a compromised extension or a backdoored repo — assume full machine compromise and rotate credentials across every service you use, not just GitHub.
The Bigger Pattern
ForceMemo demonstrates something worth taking seriously: blockchain-based C2 combined with Git history rewriting is a durable attack template. The force-push technique exploits existing permissions, not a new vulnerability. The Solana C2 can’t be taken down by seizing servers. And the attack vector — trusted developer tools — bypasses most enterprise security controls entirely.
Branch protection rules blocking force-pushes on default branches would have stopped every ForceMemo injection. That’s a one-checkbox fix in GitHub’s repository settings. Most open-source Python projects still don’t have it enabled. They should.
For a full list of indicators of compromise, see the GlassWorm Solana C2 technical analysis on The Hacker News.













