ForceMemo attacks GitHub accounts and quietly backdoors Python repositories with force-pushed malware
A new supply chain attack tracked as ForceMemo is compromising GitHub accounts and silently injecting malware into Python repositories by rewriting recent commit history. StepSecurity, which first disclosed the campaign, says the earliest confirmed injections date to March 8, 2026, and new repositories are still being hit.
The attack targets Python projects across several categories, including Django applications, machine learning code, Streamlit dashboards, and PyPI-style package repositories. In affected repos, the attacker appends obfuscated malicious code to files such as setup.py, main.py, and app.py, which means a developer can trigger the malware simply by installing from a compromised GitHub repo or by cloning and running the code.
What makes ForceMemo stand out is how little visible evidence it leaves behind. StepSecurity says the attacker takes the latest legitimate commit on a repository’s default branch, rebases it with the malware added, then force-pushes the result back while preserving the original commit message, author name, and author date. That makes the repository look normal at a quick glance, even though the code changed.
Researchers tie the account-takeover stage to GlassWorm, a separate malware operation that steals GitHub credentials and tokens from developer environments. Public follow-up coverage says GlassWorm stole tokens through infected VS Code and Cursor extensions, then used those credentials to modify repositories in the ForceMemo phase. StepSecurity’s write-up and later reporting both describe this link.

How the ForceMemo attack works
According to StepSecurity, the attacker does not open a pull request or add an obviously suspicious new commit. Instead, they take the newest clean commit, add obfuscated malware to a Python file, then replace history with a force-push. The preserved author metadata helps the malicious change blend in.
The hidden payload uses several layers of obfuscation. The sample StepSecurity analyzed decoded content through base64, decompressed it with zlib, and then applied XOR decryption with a key of 134 before moving to the next stage. The malware also checks for Russian locale or timezone settings and stops if it detects them. StepSecurity says that behavior matches a common pattern seen in Eastern European cybercrime activity.
The most unusual part comes next. The malware uses Solana blockchain transaction memos as a command channel to fetch updated instructions or payload locations. StepSecurity says it also queries nine Solana RPC endpoints as fallbacks, which makes takedown harder because the command data sits on-chain rather than on a normal server that can be seized or shut down.
Why this GitHub attack matters
This is a supply chain problem, not just an account takeover problem. If maintainers and contributors trust a repository’s default branch, they may pull infected code without realizing the last visible commit was rewritten. That can expose developers, CI pipelines, downstream users, and anyone installing packages directly from GitHub.
The attack also shows the risk of broadly scoped GitHub tokens. GitHub’s own documentation says a personal access token can act on behalf of its owner, and classic personal access tokens can grant access to all repositories the owner can reach. GitHub recommends fine-grained personal access tokens where possible because they can be restricted to specific repositories and permissions.
GitHub also warns users to treat access tokens like passwords, avoid storing them insecurely, and use secret scanning to detect leaked credentials. Those recommendations matter here because StepSecurity and related reporting indicate the attacker used stolen GitHub credentials to take over accounts and rewrite repositories.
Attack chain at a glance
| Stage | What happens |
|---|---|
| Initial compromise | GlassWorm steals GitHub credentials or tokens from developer systems |
| Account access | Attacker logs into GitHub accounts with stolen credentials |
| Repo tampering | Latest clean commit is rebased with appended malware |
| Stealth step | Attacker force-pushes the altered commit, preserving original author metadata |
| Trigger | Developers run pip install, python setup.py install, or execute cloned code |
| C2 method | Malware retrieves next-stage instructions through Solana memos |
Sources: StepSecurity and follow-up reporting on the GlassWorm connection.

Signs that a repository may be compromised
StepSecurity says one clue is a mismatch between the author date and the committer date on a recent commit. In the examples it reviewed, those gaps ranged from months to years. Another clue is a committer email set to the string null, which appears repeatedly across affected repositories.
Researchers also told developers to look for the marker variable lzcdrtfxyqiplpd inside cloned Python files. StepSecurity published a GitHub code search based on that variable and said it can help identify infected repos. The report also flags ~/init.json and an unexpected node-v22.9.0 folder as useful signs that the next payload stage may have already run.
What developers should do now
- Check recent commits on default branches for author date and committer date mismatches.
- Search cloned code for
lzcdrtfxyqiplpd, especially insetup.py,main.py, andapp.py. - Review developer machines for
~/init.jsonor an unexpectednode-v22.9.0directory. - Revoke and rotate any GitHub tokens that may have been exposed. GitHub says tokens should be treated like passwords and can be revoked if leaked.
- Move to fine-grained personal access tokens where possible, since GitHub says they can be limited to specific repositories and permissions.
- Enable secret scanning and avoid storing tokens in code or plaintext files. GitHub explicitly recommends both steps.
Key indicators
| Indicator | Detail |
|---|---|
| Malware marker | lzcdrtfxyqiplpd |
| Suspicious files | ~/init.json |
| Suspicious folder | node-v22.9.0 |
| Common targets | setup.py, main.py, app.py |
| Commit clue | Preserved author metadata but mismatched committer date |
| Tooling clue | Committer email often set to null |
Source: StepSecurity.
FAQ
ForceMemo is the name StepSecurity gave to an active attack that hijacks GitHub accounts and force-pushes malware into Python repositories while hiding the change inside rewritten commit history.
A developer can trigger the malware by installing a package directly from a compromised GitHub repository or by cloning and running the altered project. StepSecurity says the malicious code often sits in normal Python entry files such as setup.py, main.py, or app.py.
Because it preserves the original commit message, author, and author date, the changed code does not immediately look like a fresh malicious commit. Reviewers need to compare committer metadata and actual file contents to spot the tampering.
Public reporting says GlassWorm steals GitHub credentials and tokens from developer systems, including through malicious VS Code and Cursor extensions. Those stolen credentials then feed the ForceMemo repository backdoor phase.
GitHub says users should treat tokens like passwords, prefer fine-grained tokens when possible, keep scopes minimal, avoid storing tokens in code, and use secret scanning to catch leaks.
Read our disclosure page to find out how can you help VPNCentral sustain the editorial team Read more
User forum
0 messages