
September 20, 2026
6 Min Reads
Endura Security

The provenance was valid. The publishing workflow was trusted. The malware had already been seen before. None of that stopped the code from reaching developers and running inside real environments.
Software supply chain security has spent years improving our ability to answer questions about trust. Where did this package come from? Who published it? Was the build produced by the expected workflow? Does the artifact match anything we already know to be malicious? Those are important questions, and the controls built around them have made the ecosystem safer. But the attacks we have seen throughout 2026 are exposing a problem that those controls were never designed to solve.
A package can come from the right workflow and still be malicious. A release can have valid provenance and still contain poisoned source code. A short-lived credential can still be stolen while it exists in memory. A malware scanner can miss a payload, including one that researchers have already seen before.
At that point, the problem is no longer whether the software looked trustworthy before execution. The problem becomes what the software is allowed to do after execution begins. That distinction matters because attackers are increasingly finding ways to enter through legitimate identities, legitimate repositories, and legitimate release pipelines. Once they succeed, the resulting package often inherits the same access as everything else running inside the build.
That is where the security model starts to break down.
On August 4, 2026, the compromise of the Keyv and Cacheable ecosystem developed into one of the largest npm supply chain incidents of the year. SafeDep's investigation identified 2,234 poisoned versions across 444 package names, using credentials associated with twelve organizations. The worm executed through preinstall hooks and targeted cloud credentials, package registry tokens, GitHub tokens, database connection strings, private keys, and CI/CD secrets. It also attempted to inspect GitHub Actions runner memory and establish persistence in developer tooling. One package made the larger lesson especially clear: keyv@6.0.0.
The package had valid provenance. GitHub Actions published the release using OIDC, and the attestation correctly showed that the project's normal release workflow produced the package. The problem was that the source entering that workflow had already been poisoned. That does not make provenance ineffective. It means provenance answered the question it was designed to answer. It established where the artifact came from and which workflow produced it. It did not establish that the code entering that workflow was safe.
The attacker had moved earlier in the chain. Wiz also found that the campaign attempted to steal cloud and infrastructure credentials, CI/CD secrets, and developer credentials while planting persistence through Claude Code hooks and VS Code tasks.json files. Once the malicious package was executing inside a developer or CI environment, it could begin using the authority already available to that environment.
Endura approaches the problem differently because it does not have to decide whether keyv@6.0.0 is trustworthy before allowing the build to continue. Instead, it focuses on what the build actually needs to do. A dependency installation may legitimately need to read files in the workspace, write into node_modules, invoke expected build tools, and connect to approved package infrastructure. Those requirements do not imply that the same process should also be able to read SSH keys, cloud credentials, package publishing tokens, arbitrary process memory, or sensitive configuration outside the build.
Endura policies can govern those behaviors independently. File reads can be controlled with path.open. File creation and modification can be restricted with path.create and path.write. Execution can be constrained with path.execute, and outbound network access can be governed with ip.connect.
In enforce mode, behavior outside the policy can be denied rather than simply recorded. That means a normal installation could still read the source tree and write expected build output, while attempts to read ~/.ssh, ~/.aws, ~/.npmrc, or sensitive runner files could be blocked. The same policy could allow expected build processes while denying an unexpected second-stage payload, or permit connections to a package registry while refusing connections to unrelated command-and-control infrastructure.
Endura would not stop an attacker from compromising an upstream maintainer account. That is a different problem. What it can do is prevent that upstream compromise from automatically receiving the full authority of the environment where the package later runs.
Disabling package lifecycle scripts is a useful security control, and npm has taken meaningful steps in that direction. npm 12 changed install-time defaults so dependency preinstall, install, and postinstall scripts do not execute unless explicitly permitted. Remote URL dependencies and Git dependencies also became opt-in. That closes an important attack path. It does not close every attack path.
The AsyncAPI compromise in July showed why. An attacker gained push access to AsyncAPI repositories, inserted malicious code, and allowed the project's legitimate GitHub Actions release workflows to publish compromised packages through npm's OIDC trusted-publisher integration. The resulting releases carried valid provenance because the authorized release workflow really did publish them. The publishing process itself was not impersonated. The source it received had already been changed. The malicious code also avoided the obvious lifecycle hooks. It did not depend on preinstall, install, or postinstall. Instead, the dropper executed when the poisoned module was loaded during normal use.
Once active, the package launched a detached Node process, downloaded a second-stage payload through IPFS, and wrote it to a hidden location. On Linux, researchers observed the payload being written under ~/.local/share/NodeJS/sync.js. The second stage included several command-and-control mechanisms, along with credential harvesting aimed at SSH keys, npm configuration, GitHub CLI configuration, AWS credentials, Kubernetes configuration, and Docker credentials. Researchers also documented persistence capabilities involving systemd and cron. The important lesson is that blocking install scripts would not have been enough. The malicious behavior simply waited until the library was used.
From Endura's perspective, the important detail is not the package name. The important detail is the behavior that follows execution. A legitimate library load turns into a hidden child process. That child process downloads another payload. The payload is written outside the expected build output, executed, and then begins reading credentials and communicating with external infrastructure. Each step creates an enforcement opportunity.
A Node-based build may legitimately execute Node and other known build tools. That does not mean every new file written to disk should automatically become executable. A build may need Internet access, but that does not mean it needs unrestricted access to IPFS gateways, BitTorrent infrastructure, or arbitrary external hosts. The same principle applies to persistence. A build tool writing into the project workspace can be legitimate. A dependency quietly writing systemd configuration, cron entries, or hidden files under a user's home directory is a very different behavior.
Endura's Runtime Sensor observes file, process, network, credential, and resource activity from the kernel. With enforcement enabled, policies can deny operations that fall outside the behavior the build actually requires. The system does not need to recognize Miasma by name before it can act. It only needs to know that the build never required this behavior in the first place.
Malware scanning addresses another part of the supply chain problem. npm introduced automatic publish-time malware scanning in July 2026, allowing new packages to be scanned before they become generally available. That is a valuable control. It also remains a detection system, which means it will inevitably have false negatives. On September 7, Aikido researchers identified four npm package versions containing a Shai-Hulud payload.
What made the discovery unusual was that the payload was not new.
According to Aikido, it was byte-for-byte identical to a payload used during the May 19 AntV compromise. The same SHA-256 hash had appeared in hundreds of package versions in May, disappeared for 111 days, and then appeared again in newly published packages in September. By that point, npm's publish-time malware scanning had already been operating for weeks. That does not mean publish-time scanning is ineffective. Modern malware detection is difficult, especially when payloads are staged, obfuscated, or designed to appear differently depending on how they are analyzed. It does show why scanning cannot be the final security boundary.
The September Shai-Hulud payload attempted persistence through .vscode/tasks.json and .claude/settings.json, validated stolen tokens, downloaded package tarballs, injected itself, and republished packages. Even if the package is not identified as malicious before execution, those actions still look very different from the behavior expected from a normal dependency.
A scanner may fail to classify something correctly. Runtime policy does not need the same level of certainty. Without enforcement, a missed malicious package often inherits the permissions of the process running it. If the CI runner can read credentials, write developer configuration, publish packages, and make unrestricted outbound connections, the malicious package can usually attempt the same things. With enforcement, the scanner can still miss the malware while the runtime boundary remains intact.
The package might begin executing. It could then attempt to rewrite AI assistant configuration, create editor startup tasks, read sensitive credentials, or begin modifying and republishing other packages. Those operations can be denied because they were never part of the intended build behavior. The package can be unknown. The behavior does not have to be unrestricted.
The TanStack compromise in May showed another weakness in the current model, this time inside the release pipeline itself. TanStack's postmortem documented 84 malicious versions across 42 packages. The attacker did not need to successfully phish a maintainer, and there was no long-lived npm token sitting around waiting to be stolen. Instead, the attacker chained a pull_request_target workflow weakness, GitHub Actions cache poisoning, and runtime extraction of an OIDC token from the GitHub Actions runner process's memory. The release credential was short-lived. It was also legitimate. The attacker waited for the trusted environment to receive it, then stole it while it existed in memory.
That is an important distinction because short-lived credentials are often discussed as though they eliminate the credential theft problem. They reduce exposure substantially, but they do not prevent malicious code already running inside the trusted environment from trying to access the credential while it is active. The TanStack team detected the compromise quickly. Even so, the malicious packages had already been published, and remediation still required time to deprecate and remove the affected versions. Once again, execution moved faster than response.
The attack depended on behavior that an ordinary release process should not need: reading another process's memory to recover its credential. On Linux, process memory can be exposed through interfaces such as /proc/<pid>/mem. Endura's file access controls can restrict which processes are allowed to open those paths. A release runner may need to read the workspace, package metadata, source files, and build output. It does not normally need permission to inspect the memory of another process. That creates a useful security boundary. The poisoned cache could still reach the runner. Malicious code could still begin executing. But the step that converts execution into credential theft can be denied. The attacker no longer gets to assume that every process running inside the CI job can interact freely with every other process on the machine. That changes the impact of the compromise.
There is a tendency after incidents like these to conclude that provenance failed, trusted publishing failed, or malware scanning failed. That is too simplistic.
In several of these incidents, the controls were doing exactly what they were designed to do. ChainDrop's provenance identified the workflow that produced the package. AsyncAPI's provenance identified the legitimate release pipeline. TanStack's OIDC token really was issued to the trusted environment. npm really does scan packages before making them available. The problem comes from treating those facts as proof that the resulting code can safely receive broad runtime authority.
SCA tells you which components are present. SAST helps identify weaknesses in source code. Provenance tells you where an artifact came from. Trusted publishing helps confirm that publication occurred through an approved workflow. Malware scanning looks for characteristics associated with malicious code. Cooldowns give defenders more time to discover problems before adoption spreads. All of those controls have value.
None of them answers the runtime question: what is this code allowed to do once it starts running inside your environment?
That is the gap Endura is designed to address.
The Runtime Sensor observes the behavior a pipeline actually requires. Teams can derive policies around that behavior, then enforce those policies during future builds. Unauthorized file access, process execution, network activity, credential access, and other sensitive operations can be denied at the kernel layer. That turns runtime behavior into a security boundary instead of another stream of alerts.
The answer is not to abandon provenance, SBOMs, dependency analysis, trusted publishing, malware scanning, short-lived credentials, or dependency cooldowns. Use them. Each one reduces risk at a different stage of the software lifecycle. The mistake is assuming that enough pre-execution trust signals eventually make runtime restrictions unnecessary. Most pipelines still operate on an implicit model that looks something like this: verify the software, decide whether it is trusted, then let it run with the ambient authority of the build environment. That model gives a compromised package far more power than it usually needs.
A package manager may need access to a registry, but it does not need access to every credential on the machine. A compiler may need to write build output, but it does not need permission to install persistence. A test runner may need network access to a local service, but it does not need unrestricted outbound Internet access. The better model is to verify what can be verified, then execute the software with only the authority required for the build. That way, trust does not become unlimited permission.
For years, software supply chain security has focused heavily on whether we can trust the code entering the pipeline. That question still matters, but it is no longer enough. A maintainer can be legitimate while the account is compromised. A workflow can be trusted while the source entering it is poisoned. Provenance can be valid while the artifact is malicious. A short-lived publishing credential can be stolen from memory. Malware can already be known and still reach the registry again. Eventually, code you did not expect will run somewhere in your environment. The security model has to survive that moment.
The more useful question is no longer simply whether the code can be trusted. It is what the code should be allowed to do if that trust turns out to be wrong. Scanners help determine what is present. Provenance helps establish where it came from.
Endura controls what it is allowed to do.
The next malicious dependency may still make it into the ecosystem. That does not mean it should be allowed to turn a package install, test run, or release job into a breach.



