GlassWorm Is Now in Your Python Repos — What It Is, How It Works, What to Do

GlassWorm Is in Your Python Repos Now — What It Is, How It Works, What to Do

This is active and moving fast, so I’m getting straight to the point.

GlassWorm started in October 2025 as a supply chain attack targeting VS Code extensions through the OpenVSX marketplace. It likely infected over 35,000 downloads before being contained. There were two more waves — November 2025 and January 2026 — each targeting VS Code extensions with a combined reach of tens of thousands of users.

What you need to understand is what GlassWorm was designed for: stealing credentials. Specifically, GitHub tokens — harvested from VS Code extension storage, git credential files, ~/.git-credentials, and the GITHUB_TOKEN environment variable.

Now those stolen tokens are being used in a new campaign called ForceMemo. And the target is your Python repositories.


How the Attack Works

The ForceMemo campaign, active since March 8, 2026, uses credentials stolen by GlassWorm to directly access GitHub accounts of developers. Once inside, the attacker does something unusual:

Instead of opening a pull request (visible) or creating a new commit (visible), it takes the latest legitimate commit on your default branch, rebases it — adding obfuscated malicious code to key Python files — and then force-pushes the result.

The commit message stays the same. The author name stays the same. The author date stays the same. In the GitHub UI, nothing looks out of place. The only traces: the committer date changes to the actual date of the attack, and the committer email is usually set to the string "null".

The target files are setup.py, main.py, and app.py. The injected payload is encoded in Base64 and appended to the end of these files.

What does the payload do? It queries a Solana wallet — the same infrastructure used in earlier waves of GlassWorm since November 2025 — to get a command and control URL. From there it downloads additional scripts designed to steal cryptocurrency and sensitive data.

The trigger is simple: anyone who runs pip install from a compromised repo, or who clones and runs the code, activates the malware.


Who Is Affected

The attack specifically targets:

  • Django applications
  • ML research code
  • Streamlit dashboards
  • PyPI packages

Approximately 150+ GitHub repositories were compromised between March 3 and March 9 in GlassWorm’s Unicode wave. Hundreds more were affected in ForceMemo’s force-push wave starting March 8. Both attacks trace to the same Solana infrastructure — meaning the same actor is running multiple campaigns simultaneously.

A Reddit user discovered the compromise by noticing that "null" had made commits on most of their repos — and traced the infection back to a compromised Cursor extension. This matters: if you’re using Cursor or VS Code extensions from unofficial sources, it’s possible your credentials were already stolen without you knowing.


Why It’s Hard to Detect

Three things make ForceMemo particularly dangerous:

1. No pull request trail. Because the attack uses rebase with force-push instead of new commits, GitHub’s activity feed shows nothing unusual. There’s no PR to review, no new commit to notice.

2. Invisible Unicode in the parallel GlassWorm wave. The related Unicode campaign hides its payload using characters from Unicode’s Private Use Area (U+FE00–U+FE0F) — characters that render as zero-width spaces in every editor, terminal, and code review interface. Visual review offers no protection.

3. Infection starts in your tools. GlassWorm infected VS Code and Cursor extensions. It’s possible you’ve been running it for months before ForceMemo converted those stolen credentials into repo compromises.


What to Do Right Now

1. Audit your GitHub tokens immediately.
Go to GitHub Settings → Developer Settings → Personal Access Tokens. Revoke any token you don’t recognize or haven’t used recently. If you’re in an organization, review all member tokens.

2. Enable branch protection rules that block force-pushes.
On GitHub: Settings → Branches → Add rule → Enable “Require pull request reviews before merging” and “Do not allow bypassing the above settings.” This prevents force-pushes to your default branch even with valid credentials.

3. Review your repos for the attack signature.
Look for commits where the committer email is "null" or where the committer date doesn’t match the author date in recent commits. These are the primary signals of a ForceMemo compromise.

4. Scan Python files for unexpected Base64 at the end.
Check your setup.py, main.py, and app.py for suspicious Base64 blocks at the end of the file. Legitimate code normally doesn’t look like this.

5. Audit your VS Code and Cursor extensions.
Remove any extension you’re not actively using. Be especially cautious with extensions installed from OpenVSX or third-party sources. Verify that extensions you do use haven’t had unexpected recent updates.

6. If you maintain a PyPI package, notify your users.
If your package was in the affected window (since March 8), assume compromise until proven otherwise and publish a new clean release.


The Big Picture

GlassWorm is now a multi-vector campaign: VS Code extensions, Cursor extensions, npm packages, and now Python repos on GitHub — all sharing the same Solana infrastructure. The attack is evolving from “infect developer machines” to “use developers as vectors into the supply chain.”

The development ecosystem — ML repos, open source packages, internal tools — is a high-value target. And the AI tools layer (VS Code extensions, Cursor extensions) turns out to be a perfect initial infection point, because developers install them quickly and trust them implicitly.

Review your repos. Audit your tokens. Enable force-push protection. The campaign is active right now.


Already reviewed your repos? If you found something, share in the comments — you help others in the community know what to look for. :speech_balloon: