Blog

When a Package Becomes an Entry Point

Recent attacks against npm, PyPI, GitHub Actions, and CI/CD plugins show that packages and build pipelines are part of the security perimeter. The real impact depends on which keys and permissions a compromised process can reach.

8 min read CloudForge
Supply chainCI/CDSecurityOpen source
Diagram showing a compromised package moving through a CI/CD pipeline and gaining access to tokens, SSH keys, kubeconfig, and cloud credentials
A compromised package becomes most dangerous when it runs in an environment with access to infrastructure and secrets.

Attacks against software packages have shifted over the last few months. This is no longer only about a malicious library hidden somewhere in a dependency tree. More often, attackers are abusing trust in the whole distribution chain: package registries, Docker images, GitHub Actions, Jenkins plugins, IDE extensions, and security tools.

The shared goal is simple: get code into an environment where tokens, SSH keys, cloud credentials, registry access, or Kubernetes configuration are available. In other words, exactly where infrastructure is built and operated today.

For companies that use open source, containers, CI/CD, and cloud infrastructure, this requires a change in thinking. A package is not just an application dependency anymore. During installation, build, or deployment, it becomes part of the security perimeter.

Diagram of a compromised package moving through a trusted environment toward data exfiltration
The real impact of an incident is not determined only by the affected package, but mainly by the environment where it runs.

The Latest Wave: May 2026

The most visible May case is the campaign referred to as Mini Shai-Hulud. According to reports from Wiz, The Hacker News, Hackread, and other security teams, it hit npm and PyPI packages across several ecosystems on May 11 and 12, 2026. Reported targets included TanStack, UiPath, Mistral AI, OpenSearch, and Guardrails AI.

The scale was not small. Public analyses mentioned more than 170 affected packages and hundreds of malicious versions. Some of the packages were well-known projects used for web development, automation, AI integrations, and search.

The mechanism is more interesting than the number itself.

In the TanStack case, incident analyses indicate that the attackers did not obtain a classic npm token. They abused a chain in GitHub Actions: pull_request_target, poisoned cache, and an OIDC token from a running runner. Malicious versions could then be published through the legitimate release process. Researchers also noted that some packages carried valid SLSA provenance information. That is an uncomfortable detail: a mechanism designed to verify package origin can confirm that a package passed through the official pipeline, but not that the pipeline itself was not abused.

PyPI variants included packages such as mistralai==2.4.6 and guardrails-ai==0.10.1. According to analyses, they downloaded an additional malicious component from git-tanstack[.]com and ran a credential-stealing tool. Again, the targets were cloud access, GitHub tokens, registry tokens, Kubernetes service accounts, Vault, and other secrets available in the environment.

The campaign had another unpleasant property: several independent exfiltration paths. Analyses described a combination of a lookalike domain, the decentralized Session network, and repositories created through the GitHub API. In practice, that means blocking a single destination is not enough.

Checkmarx: When the Security Tool Is Affected

A second May example shows a different problem. In its ongoing updates, Checkmarx mentioned a malicious version of the Checkmarx Jenkins AST plugin published to the Jenkins Marketplace on May 9, 2026. According to the published incident update, the affected window ran from May 9 at 01:25 UTC to May 10 at 08:47 UTC.

Checkmarx had already been handling a broader supply chain incident that touched KICS Docker images, a GitHub Action, and extensions for VS Code/Open VSX. With tools like these, the potential impact can be larger than with a regular application library. A security scanner or CI plugin often sees repositories, build logs, environment variables, infrastructure configuration, and sometimes deployment credentials.

In other words: a tool that is supposed to help find infrastructure flaws can, if compromised, become a path to infrastructure secrets.

March and April Were Not Exceptions

May continued a series of earlier incidents.

Timeline of selected software supply chain incidents
Incidents repeated across ecosystems, registries, and CI/CD tools.

For LiteLLM, compromised versions 1.82.7 and 1.82.8 were published to PyPI in March 2026. In its security notice, the project said the malicious code targeted environment variables, SSH keys, cloud credentials, Kubernetes tokens, and database passwords. One especially important detail involved a .pth file in Python site-packages, which can execute automatically when the interpreter starts, even without explicitly importing the library.

For Xinference, OX Security reported affected PyPI versions 2.6.0, 2.6.1, and 2.6.2. The malicious code ran on import and collected AWS, GCP, and Kubernetes configuration, SSH keys, API secrets, database access, shell history, SSL certificates, and in some cases cryptocurrency wallet data.

In the npm ecosystem, CanisterSprawl appeared as an attack against the pgserve package. Malicious versions used a postinstall script, searched for publishing tokens, and under the right conditions tried to spread further through packages that the compromised user was allowed to publish. Decentralized infrastructure was also mentioned as a C2 channel.

These examples differ by language, registry, and technical detail. But they follow the same pattern: a package runs in a trusted environment and extracts secrets from it.

The Core Problem Is Permissions

When dealing with supply chain attacks, the first question is often: "Did we use the affected version?" That is the right question, but it is not enough.

The more important follow-up is: "What could the process access at that moment?"

Comparison of broad and limited impact from a malicious package in CI/CD
The same malicious package has a completely different impact depending on permissions, isolation, and outbound traffic in the pipeline.

If a malicious package runs in an isolated test without secrets and without outbound internet access, the impact may be limited. If it runs in a CI job that has a long-lived cloud key, a GitHub token, an npm publishing token, and access to a production Kubernetes cluster, the incident is very different.

The same applies to developer workstations. A developer laptop often contains SSH keys, .env files, cloud CLI sessions, kubeconfig, registry tokens, and command history. A compromised package does not have to attack production directly. It only needs to collect data from an environment that manages production.

What This Means for Infrastructure Operations

Open source is not the problem. Unmanaged trust is.

Open-source infrastructure gives companies control, transparency, and less dependence on vendors. But without operational rules, it can easily become a collection of tools with too many permissions and too little oversight.

From an infrastructure perspective, six areas matter most.

1. Pin Versions, Digests, and Workflow References

Unpinned dependencies and floating tags such as latest increase the risk that a build downloads a malicious version during a short compromise window. For critical components, it makes sense to pin exact versions, Docker digests, and GitHub Actions references.

This is not only about application libraries. CI/CD plugins, scanners, base images, IDE extensions, and internal tools deserve the same attention.

2. Limit CI/CD Job Permissions

A build job should not automatically have access to production secrets. A test pipeline does not need deployment rights. A scanner that reads a repository should not be able to modify cloud infrastructure.

The principle of least privilege is familiar, but in CI/CD it is often bypassed for convenience. Supply chain attacks show why that shortcut is expensive.

3. Replace Long-Lived Keys With Short-Lived Identities

Static keys stored in CI/CD variables or on developer machines are ideal targets for credential-stealing tools. Where possible, it is better to use short-lived tokens, OIDC federation, workload identity, and dynamically issued secrets.

Short-lived access will not prevent every incident. It does, however, significantly reduce the time window in which a stolen key is useful.

4. Monitor Outbound Traffic From Build Environments

Many incidents end with data being sent to an external destination. If a CI runner can communicate anywhere, detection becomes harder. It is useful to log DNS and HTTP requests from CI/CD, watch for unusual destinations, and restrict outbound traffic for sensitive pipelines to the services they actually need.

Observability is not only about application performance. In modern infrastructure, it is part of security.

5. Know Where a Package Actually Ran

During an incident, opening the dependency tree is not enough. You need answers to operational questions:

  • Was the affected version present in a lockfile?
  • Was it downloaded during a Docker image build?
  • Did it run in GitHub Actions, GitLab, Jenkins, or locally?
  • Which secrets were available to that job?
  • Do we have logs that can prove this later?

Answering those questions requires lockfile discipline, SBOMs, audit logs, centralized logging, and a readable CI/CD architecture.

6. Prepare Secret Rotation Before the Incident

With a compromised package, teams quickly reach an uncomfortable question: what do we need to revoke and issue again?

Six steps for rotating secrets after an incident
Secret rotation should not be invented during an incident. It needs to be prepared in advance.

If a company does not know where keys are stored, who owns them, and how they are replaced, incident response turns into improvisation. For critical secrets, there should be a procedure: find them, revoke them, generate new ones, deploy them, and verify that the old ones no longer work.

A Practical Test for Your Environment

A simple control question is:

What happens if a malicious postinstall script runs in our pipeline today?

A good answer should include concrete limits:

  • it runs in an isolated runner,
  • it has no production credentials,
  • outbound traffic is restricted,
  • short-lived tokens are used,
  • installed versions are traceable,
  • logs can show where the code ran,
  • secret rotation has a defined process.

If the answer is "I do not know", that is not a failure. It is a good starting point for hardening.

Security as Day-2 Operations

Supply chain incidents are not a one-off mistake that a single audit can solve. They are operational events. They involve how dependencies are updated every day, how builds run, who can publish packages, where secrets live, and how quickly they can be revoked.

That puts them in the same category as monitoring, log management, hardening, and infrastructure operations. Not as a paperwork exercise, but as an ongoing operational process.

The goal is not to stop using open source or automation. The goal is to have infrastructure that is readable, limits blast radius, and gives the team enough data to respond quickly.

In other words: open source and CI/CD remain the right path. They just cannot be operated as a set of trusted black boxes anymore.

Conclusion

The May attacks against npm, PyPI, and CI/CD tools show that a trusted release process can become an attacker's distribution mechanism.

So the question is not only: "Do we have a vulnerable package?"

The better question is: "If malicious code runs in our build, scanner, or developer workstation, what can it reach?"

The answer to that question determines the real impact of the incident.