StepSecurity threat intelligence has identified an active campaign dubbed “ForceMemo” targeting hundreds of GitHub accounts and Python repositories. The attack utilizes sophisticated force-pushes to inject malware into project files like setup.py and main.py. Campaign activity dates back to March 8, 2026, and remains ongoing with new compromises being detected daily. This development poses a severe risk for developers who install packages or clone code directly from GitHub, as the malicious code is triggered immediately upon execution.
Significance: The attack bypasses traditional security visibility by overwriting git history rather than using pull requests. Connection to Glassworm: The breach originates from compromised developer environments via malicious IDE extensions. This represents a tactical shift from targeting repository infrastructure to targeting the developer’s local tools, such as VS Code and Cursor, which often hold elevated permissions and secrets. By compromising the source of the code, attackers ensure that malicious modifications appear as legitimate updates from authorized authors.
Scope and Discovery of the ForceMemo Campaign
StepSecurity researchers discovered the ForceMemo campaign after detecting identical malware injections across a vast array of Python repositories starting on March 8, 2026. While initial reports from Tom’s Hardware cited 151 specific repositories and VS Code instances affected, StepSecurity indicates the total number of compromised accounts and projects reaches into the hundreds. The campaign is characterized by its persistence, as researchers continue to track and update the list of newly infected repositories as the threat actor remains active.
The diversity of the targets suggests a broad interest in the Python ecosystem rather than a narrow vertical. Affected projects include Django applications, Machine Learning (ML) research code, Streamlit dashboards, and established PyPI packages. By targeting such a wide variety of software, the attacker maximizes the potential for downstream infections across different sectors of the technology industry.
The focus on ML research code and web frameworks like Django is particularly notable for security analysts. These projects often handle sensitive data or serve as the backbone for enterprise-grade applications. Compromising these repositories allows the attacker to gain a foothold in environments where credentials, data sets, and API keys are frequently utilized. This broad targeting strategy likely aims to cast a wide net for high-value credentials that can be leveraged for further corporate espionage or financial gain.
Furthermore, the inclusion of Streamlit dashboards indicates a specific interest in data science environments. These dashboards are often used to visualize internal business metrics, making them lucrative targets for data exfiltration. The ongoing nature of the campaign suggests that the attacker has established a successful and repeatable workflow for identifying and compromising vulnerable developer accounts.
The Mechanics of the “Force-Push” Injection
The ForceMemo campaign stands out due to the sophistication of its injection method, which avoids standard GitHub activity notifications. Rather than opening a pull request or creating a new commit—both of which would trigger alerts in a repository’s activity feed—the attacker uses a force-push to overwrite existing history. This method ensures the malicious changes are integrated into the default branch without leaving the usual forensic trail of a new contribution.
To maintain a high level of stealth, the attacker utilizes git rebasing. They rebase legitimate, existing commits with the malware appended, which preserves the original author details, timestamps, and commit messages. To a casual observer or a developer performing a quick review of the commit history, the repository appears unchanged and authenticated by the original maintainer.
The malicious code is typically appended to the end of critical Python project files such as setup.py, main.py, and app.py. These files are chosen because they are frequently executed during the installation or initialization phase of a project. For instance, any user who runs a `pip install` command directed at a compromised repository will inadvertently trigger the malware during the package setup process.
This preservation of git history creates a profound false sense of security for downstream users. In modern DevOps workflows, many automated systems and developers rely on the “Author” and “Date” fields of a commit to verify its legitimacy. By manipulating these fields through force-pushes, the attacker effectively subverts the trust-based model of open-source collaboration. This technique forces a shift in defensive strategy, requiring users to verify the actual content of the code against known-good hashes rather than relying on git metadata.
The choice of setup.py is especially dangerous due to its role in the Python packaging ecosystem. Because this file is designed to execute arbitrary code to configure an environment, it provides the perfect cover for a stage-one dropper. Developers often run setup scripts with elevated privileges, further increasing the potential impact of the initial infection on the local workstation or build server.
Glassworm Malware and IDE Extension Compromise
The root cause of these repository compromises has been traced back to infected developer workstations. Researchers identified that developers were first compromised by the GlassWorm malware, which was delivered through malicious extensions for VS Code and Cursor. These extensions, appearing as legitimate productivity tools, served as the initial entry point into the developer’s local environment.
GlassWorm’s stage 3 payload includes a sophisticated module specifically designed for the theft of credentials and authentication tokens. It systematically harvests GitHub-related secrets from multiple local sources, including the `git credential fill` command, VS Code’s internal extension storage, the `~/.git-credentials` file, and the `GITHUB_TOKEN` environment variable. Once these tokens are exfiltrated to the attacker, they provide full administrative access to the victim’s GitHub repositories.
Armed with these stolen credentials, the attacker automates the process of force-pushing malware into every repository associated with the compromised account. This automated secondary phase allows the campaign to scale rapidly, as a single developer compromise can lead to the infection of dozens of projects simultaneously. The use of legitimate tokens also bypasses most multi-factor authentication (MFA) protections, as the tokens themselves represent an already authenticated session.
This attack vector highlights a critical vulnerability in the modern IDE ecosystem. Developers increasingly rely on a vast marketplace of third-party extensions to enhance their coding workflows. These extensions often operate with the same permissions as the user and have direct access to the local filesystem and environment variables. If an extension is malicious or becomes compromised, it can easily access the sensitive tokens required to manage remote repositories.
The targeting of Cursor extensions alongside VS Code suggests the threat actor is aware of the growing popularity of AI-native code editors. These editors often require deep integration with a developer’s codebase and secrets to function effectively, making them high-value targets for credential harvesting. The ability of GlassWorm to pivot from a local IDE extension to a global repository compromise demonstrates a highly effective and modern supply chain attack chain.
Technical Analysis of the Malicious Payload
The injected code utilizes a heavy obfuscation wrapper to evade static analysis and simple grep-based detection. The malware is typically a 4,800-character Base64-encoded blob that is decompressed using the `zlib` library. The script then uses a lambda function to perform a bitwise XOR operation against a fixed integer (134) to decrypt the final payload before executing it via the `exec` function.
Once the initial Python script is active, it establishes a more robust execution environment on the victim’s machine. It is programmed to download a specific version of Node.js (v22.9.0) directly from nodejs.org. This Node.js binary is then used to execute a separate, AES-encrypted JavaScript payload that contains the core malicious logic for the next stage of the attack.
Interestingly, the malware includes specific evasion tactics based on the geographic location of the host system. The script is designed to skip the execution of its payload if the system’s locale or timezone settings indicate that the machine is located in Russia. This “No Russia” rule is a common signature in the cybersecurity world, often used by threat actors to avoid local law enforcement scrutiny or as an indicator of the actor’s own regional origin.
The requirement for a specific Node.js version suggests that the attacker’s stage-two tools are built on modern JavaScript features that require a recent runtime. By downloading the binary directly, the malware ensures it can run regardless of whether the victim already has Node.js installed. This self-contained approach increases the reliability of the malware across different operating systems and developer configurations.
The use of AES encryption for the JavaScript payload further complicates forensic analysis. Without the specific key retrieved during the execution flow, security tools cannot inspect the malicious logic. This multi-layered approach—Python to Node.js to encrypted JavaScript—shows a high level of operational security intended to frustrate both automated sandboxes and human researchers.
Blockchain-Based Command and Control (C2)
A unique aspect of the ForceMemo campaign is its reliance on the Solana blockchain for command-and-control (C2) infrastructure. Instead of connecting to a traditional domain or IP address that could be easily blocked by firewalls, the malware queries the Solana blockchain to receive instructions. Specifically, the code queries a dedicated Solana address: `BjVeAjPrSKFiingBn4vZvghsGj9KCE8AJVtbc9S8o8SC`.
The malware looks for transaction “memos” associated with this Solana address. These memos are small text fields in blockchain transactions that, in this case, contain the URLs for the next stage of the malicious payload. By using a public blockchain, the attacker ensures that their C2 channel is highly resistant to censorship and takedown efforts, as the blockchain is decentralized and immutable.
This technique allows the attacker to update the payload URLs in real-time by simply sending a new transaction to the monitored Solana address. Any infected system checking the blockchain will immediately see the updated memo and redirect its download request to the new infrastructure. This level of agility makes it extremely difficult for defenders to “sinkhole” the campaign or cut off the malware’s ability to communicate with its creators.
The use of blockchain memos for C2 also provides a layer of anonymity for the threat actor. While the transactions are public, the identity of the person sending the Solana transactions remains hidden behind a cryptographic wallet. This method avoids the need for registering domains or renting servers that require identity verification, which are traditional weak points where law enforcement can intervene.
From a technical standpoint, querying a blockchain often looks like legitimate web traffic to many security monitoring tools. Many developers use blockchain-related tools or APIs, so a request to a Solana RPC node might not trigger the same alerts as a request to a known malicious domain. This helps the malware maintain a low profile while still receiving reliable, high-speed updates from the C2 infrastructure.
Affected Organizations and Identification of Victims
The campaign has impacted a wide range of organizations, including educational institutions and open-source development teams. StepSecurity highlighted that organizations such as `wecode-bootcamp-korea` and the `HydroRoll-Team` were hit particularly hard, with each organization seeing at least six of their repositories compromised by the malicious force-pushes. The total number of affected developer accounts across the GitHub ecosystem is estimated to be in the hundreds.
The impact on educational groups like bootcamps is significant, as these environments often involve many junior developers who may be less familiar with advanced security practices. A compromise in a bootcamp repository can lead to the infection of dozens of students’ personal machines, creating a massive secondary wave of victims. These students may then inadvertently carry the malware into their future workplaces, further extending the reach of the ForceMemo campaign.
The targeting of teams like HydroRoll-Team suggests that the attacker is also interested in established open-source projects. These teams often have multiple contributors, any one of whom could be the “patient zero” through a compromised IDE extension. Once one maintainer’s token is stolen, the entire project’s codebase can be weaponized against its user base in a matter of seconds.
Educational and open-source teams are often high-value targets because they may lack the budget for premium security monitoring tools that detect force-pushes or anomalous token usage. This makes them an ideal staging ground for larger campaigns. By compromising these trusted entities, the attacker can leverage their reputation to infect more cautious users who would otherwise be wary of unknown repositories.
Mitigation and Defensive Recommendations
StepSecurity recommends that all Python developers exercise extreme caution when interacting with GitHub repositories, especially those used as direct sources for `pip install`. Because the malware overwrites history, standard visual checks of the repository are insufficient. Developers should verify that the code on the default branch exactly matches the last legitimate commit from the original author, looking for any unexpected appended code at the end of `.py` files.
Organizations are urged to audit the extensions installed in their developers’ IDEs, specifically VS Code and Cursor. Any extension that is not from a highly trusted publisher should be treated with suspicion. Additionally, security teams should review the permissions and usage history of `GITHUB_TOKEN` environment variables and other stored git credentials to identify any unauthorized force-push activity.
A broader defensive strategy should include the implementation of branch protection rules on all critical repositories. By disabling the ability to force-push to the default branch, organizations can effectively neutralize the primary injection vector used in the ForceMemo campaign. Requiring signed commits can also help ensure that only verified authors can modify the codebase, making it much harder for an attacker to spoof legitimate history.
Furthermore, developers should consider using specialized tools to monitor for secret exfiltration. Since GlassWorm specifically targets credential stores, monitoring for unusual access to `~/.git-credentials` or the VS Code storage folder can provide an early warning of an infection. Rotating GitHub personal access tokens (PATs) regularly and using short-lived, fine-grained tokens can also limit the window of opportunity for an attacker if a compromise does occur.
Conclusion
The ForceMemo campaign is still active, and StepSecurity continues to update its findings as the situation evolves. This attack marks a significant evolution in supply chain threats, combining the exploitation of the IDE extension ecosystem with the decentralized resilience of blockchain technology for command and control. The ability of the threat actor to hide malicious code within legitimate git history via force-pushes challenges long-standing assumptions about the integrity of authenticated repositories.
The long-term implications for GitHub’s repository integrity are profound. As attackers move closer to the developer’s workstation, the traditional perimeter of the repository becomes less relevant. This campaign serves as a stark reminder that the security of a project is only as strong as the security of the local tools used to build it. Maintaining a secure supply chain now requires a holistic approach that includes auditing local developer environments, enforcing strict repository permissions, and constantly verifying the code itself against unauthorized modifications.
Sources
- stepsecurity.io — ForceMemo: Hundreds of GitHub Python Repos Compromised via Account Takeover and Force-Push
- thisweekin4n6.com — This Week In 4n6
- tomshardware.com — Invisible malicious code attacks 151 GitHub repos and VS Code — Glassworm attack uses blockchain to steal tokens, credentials, and secrets | Tom’s Hardware
Frequently Asked Questions
What is the ForceMemo campaign?
ForceMemo is an active cyberattack campaign that uses malicious force-pushes to inject malware into hundreds of GitHub Python repositories by overwriting git history.
How does the ForceMemo attack bypass GitHub security notifications?
The attack uses git rebasing and force-pushes to overwrite existing history instead of creating pull requests, which prevents standard activity alerts and preserves original author details.
How are developer accounts initially compromised in this campaign?
Attackers infect developer workstations using malicious VS Code and Cursor extensions that deploy GlassWorm malware to steal GitHub authentication tokens.
What is unique about the ForceMemo command-and-control (C2) infrastructure?
The campaign utilizes the Solana blockchain to receive instructions via transaction 'memos,' making the C2 channel resistant to traditional firewalls and censorship.








