Thierry Abalea

Sep 20, 2025

An Open Letter to Microsoft: Open Source needs safer npm and GitHub Actions

In just three weeks, the JavaScript ecosystem has endured three major supply chain attacks: nx s1ngularity, Ghost Action, and Shai Hulud. Each exploited unprotected GitHub Actions workflows and the weak npm foundation. Each resulted in massive secret thefts, corrupted packages, and, in the case of Shai Hulud, even a self-replicating worm. Together they compromised nearly 500 npm packages, exposed over 850 private repositories, and harvested thousands of secrets from GitHub, AWS, Azure, GCP, DockerHub, and PyPI. Security companies themselves were not spared.

These incidents are not isolated events. They are symptoms of a deeper structural weakness: open source infrastructure, especially npm and GitHub Actions, remains insecure by default. The tools and protections to prevent or at least contain such incidents already exist, both commercial and open source, but they are optional, hard to configure, and too often overlooked by maintainers already overwhelmed by other responsibilities.

The lesson is clear. Vendors of critical open source infrastructure must make security the default. At least for open source projects. We understand the need to monetize security features for for-profit companies, but the open source ecosystem should not be left exposed. And because npm and GitHub Actions sit at the center of today’s software supply chain, we direct this call first and foremost to Microsoft.


The Two First Attacks

The story begins at the end of August 2025, with the nx s1ngularity campaign (StepSecurity write-up, Aikido, Socket, GitGuardian). Attackers discovered two vulnerabilities in a GitHub Actions workflow of the popular open source project nx. The workflow had been generated with Claude Code, reviewed by a maintainer, and accepted as legitimate. Yet it contained both a Pwn Request vulnerability and an injection flaw that together allowed attackers to exfiltrate the project’s npm token directly from CI. With this token, they pushed a malicious nx package to the registry.

The consequences were severe. Developers who installed the corrupted package had their machines infected. The malware scanned their systems for secrets, but it did not stop there. For the first time, attackers weaponized local LLM tools installed on developers’ machines, Claude, Gemini CLI, and Amazon Q, tricking them with a single malicious prompt into extracting as many secrets as possible. The exfiltrated data was then written into public GitHub repositories, double base64-encoded for obfuscation. By the time the attack was uncovered, it had stolen 2,349 credentials from 1,079 developer systems, including accounts belonging to security companies. This was not a trivial incident. It was a sophisticated, multi-stage operation that exposed just how fragile GitHub Actions workflows and npm publishing still are.

Barely a week later, on September 5th, a new attack emerged: Ghost Action (GitGuardian post, StepSecurity). The attackers’ method was cruder, but no less damaging. They committed malicious GitHub Actions workflows into 817 repositories, each designed to silently exfiltrate secrets whenever the workflows ran. The result was the theft of 3,325 secrets from 327 GitHub users. Tokens for PyPI, npm, and DockerHub were among those stolen. Popular projects like Fastuuid, itself a dependency of LiteLLM and many others, were directly affected. GitGuardian, which detected the campaign, reported that there was no overlap with nx s1ngularity’s victims. Proof that the attack surface was vast and unprotected. Once again, the absence of default safeguards in GitHub Actions had opened the door.


The Third Attack, or How Volcanoes Quiver …

The third attack, Shai Hulud (StepSecurity analysis, Socket, Aikido, GitGuardian) quivered at the limit of eruption on September 14th. Within hours, it proved to be one of the most severe supply chain compromises the JavaScript world has seen. It began with corrupted npm packages that, once installed, infected the developer’s machine. The malware immediately deployed Trufflehog to search for secrets. With freshly acquired cloud credentials for AWS, GCP, and Azure, it invoked provider SDKs and CLIs to enumerate additional secrets, this time cloud ones. These were stored in JSON files, double base64-encoded, and uploaded to GitHub in newly created public repositories named “Shai-Hulud,” ironically referencing the giant worm of Dune.

But the worm did not stop at the local machine. It created a shai-hulud branch across all repositories where the victim had write access, then committed a malicious GitHub Actions workflow. As soon as the workflow ran, it exfiltrated repository secrets to attacker-controlled webhooks and wrote them into workflow logs. It also made private repositories public. GitGuardian later reported at least 850 private repos forcibly exposed. Finally, the malware published new corrupted versions of every npm package owned by the victim, turning itself into a worm capable of downstream propagation. In total, nearly 500 npm packages were compromised, including security-related libraries such as those maintained by CrowdStrike. Thousands of secrets were stolen, and a broad swath of the ecosystem was left vulnerable.


… Before They Erupt. Be Prepared

Researchers noted the low virality of the worm, which they supposed could be due to flaws in its code. Charlie Eriksen of Aikido Security explained in his company blog that most compromised packages appeared to have been uploaded manually by the attackers rather than spreading automatically, and mistakes in the propagation logic likely prevented full-scale contagion. Rami McCarthy of Wiz observed on X that either something in the post-propagation code had failed, or GitHub itself had stepped in. Adnan Khan, a well-known GitHub Actions security researcher, was blunt: “Clever? yes. Sophisticated? no. We’re talking actors with 10–20% of the skillset of real supply chain researchers.”

Still, the worm had gathered thousands of secrets. As Eriksen warned: “They now have even more credentials they have been able to steal. This is likely not the last we will see of them.”


A Slow and Fragmented Response

The worm’s damage was serious, but the lagging response from platforms made the situation even worse. On the afternoon of September 15th, developer Daniel Pereira noticed suspicious “Shai-Hulud” repositories inside the NativeScript organization. They contained leaked secrets. He immediately emailed GitHub security but received no acknowledgment. Two days later, a reply came. He escalated through a personal contact at GitHub, who raised an internal ticket. Again, two days passed before any response. Pereira also contacted npm security, with the same two-day silence.

Out of options, he turned to the JS Foundation Slack channel, where Wesley Todd finally noticed. After nearly five hours of attempts, Todd made the first public post on BlueSky and alerted Socket. Only then did the security community mobilize, and only then did npm packages begin to be taken down.

The timeline, reconstructed thanks to the work of Mackenzie Jackson, Developer and Security Advocate at Aikido Security, is damning. For five critical hours, the worm spread unchecked. For two days, reports filed through official security channels were ignored. The first effective action came not through official response teams but through a Slack channel and a social post by a persistent developer. It was not a professional security researcher who raised the alarm but an attentive member of the community.


Protections Exist, But Not by Default

The common thread through all three attacks is clear: attackers are after secrets, and the supply chain is a soft target. Third-party dependencies carry enormous risk. Open source projects distribute widely, defend poorly, and offer attackers high-value access.

And yet, the defenses are already here. GitHub’s CodeQL static analyzer is free for open source projects and capable of scanning workflows for vulnerabilities (docs). npm could disable pre/postinstall scripts by default, as Charlie Eriksen argued on X, recommending npm install --ignore-scripts unless explicitly approved. Secrets scanners like GitGuardian’s are available for free for public repositories and small private teams. Their Has My Secret Leaked service acts as a “Have I Been Pwned” for non-human identities. Cooldown mechanisms delay the adoption of newly published packages, giving time for poisoned releases to be caught. Endor Labs has explained this concept, and it is already implemented in StepSecurity and supported in Dependabot since July 2025.

Since the same month, npm has supported Trusted Publishing with OIDC, eliminating long-lived tokens and blocking token-theft attacks (docs). GitHub Actions can be hardened using StepSecurity, which enforces outbound controls, pins actions to commit SHAs, restricts GITHUB_TOKEN permissions, and even rates third-party actions for trust. Strong open source projects like Zizmor, authored by William Woodruff (a contributor to PyPI’s Trusted Publishers), offer static analysis for Actions workflows. Shipfox is proud to sponsor it.

The problem is not the absence of solutions. It is that every single one of them requires awareness, expertise, and time to configure. For most open source maintainers, that is a luxury they do not have.


Our Call to Microsoft

npm and GitHub Actions are crown jewels in the open source ecosystem, and thus prime targets for attackers. Microsoft owns both. With that ownership comes responsibility. It is time to make security the default. At minimum for open source projects, where maintainers often lack resources to configure protections themselves. Monetization can still make sense for enterprise users, but the baseline for the open ecosystem must be secure by default.

We call on Microsoft to enable CodeQL scanning automatically on all public repositories, to disable lifecycle scripts in npm installs by default, to phase out npm tokens in favor of Trusted Publishing everywhere, and to harden GitHub Actions runners out of the box.

Commercial vendors have already demonstrated that these protections are possible. Open source projects have pioneered them. Now Microsoft must adopt them at the platform level.


A Call to the Community

While we wait for Microsoft to act, open source maintainers cannot remain idle. Even small steps help: enabling CodeQL, disabling lifecycle scripts, setting up a secrets scanner, using dependency cooldowns, and switching to Trusted Publishing.

At Shipfox, we commit to doing more than writing this letter. We are integrating security features directly into our alternative GitHub Actions runners and building partnerships with security companies to accelerate change. As the saying goes, we will put our money where our mouth is.


Acknowledgments

The quick alerts and actions of individuals like Daniel Pereira, Wesley Todd, and Charles Brossollet, Engineering Lead at GitGuardian, were essential in mitigating the impact of these attacks. Their vigilance gave the community time to respond.

The detailed analyses and write-ups from the security teams at StepSecurity, Aikido Security, Socket, and GitGuardian provided the foundation for this post and continue to help the ecosystem understand and learn from these incidents.


References

StepSecurity

Company blog: https://www.stepsecurity.io/blog

Aikido Security

Company blog: https://www.aikido.dev/blog

Socket

Company blog: https://socket.dev/blog

GitGuardian

Company blog: https://blog.gitguardian.com


Accelerate your CI with Shipfox

Try for free
Authors
Thierry Abalea

Thierry Abalea

Co-founder & CEO

Share
Twitter
LinkedIn
Reddit