The obvious version of today's SAP npm story is that four popular packages were poisoned and developers need to rotate credentials.

True, but too small.

The part worth paying attention to is how ordinary the surrounding machinery looked. According to multiple security write-ups, the attacker did not need some exotic package-registry zero day. They allegedly used stolen publisher access, release automation, and the victim's own GitHub and editor workflows to keep the infection moving. That is a worse story than "malicious package on npm" because it lives inside the path teams already trust to ship software.

What is actually verified

The Reddit-hot thread in r/programming linked SafeDep's incident write-up on April 29. SafeDep says four SAP ecosystem packages were published with a malicious preinstall hook on the same day: mbt@1.2.48, @cap-js/sqlite@2.2.2, @cap-js/postgres@2.2.2, and @cap-js/db-service@2.10.1.

StepSecurity independently reported the same four compromised versions and said it disclosed the issue to SAP by opening GitHub issues in the affected repositories at 12:03 and 12:04 UTC. Those issue timestamps are public. SAP-side response is public too. In the cap-js/cds-dbs repository, PR #1592 says an unauthorized actor pushed malicious commits that hijacked the release workflow and that future npm publishing should require manual approval. That is not outside commentary. It is the project's own remediation rationale.

Across the vendor analyses, the shared technical core is consistent. The malicious releases added setup.mjs and an obfuscated execution.js payload. The preinstall hook ran node setup.mjs, which fetched the Bun runtime and then executed the larger payload. SafeDep, StepSecurity, and Snyk all describe credential theft focused on GitHub tokens, npm tokens, and cloud credentials.

That much is solid enough to state plainly: there were malicious package releases, they used install-time execution, and the package owners are now changing release controls because the publish path was abused.

The sharper lesson is about trust boundaries, not package hygiene

If this had just been another typo-squatted package or one-off maintainer credential leak, it would still matter. What makes this one more useful as a systems story is the release path.

StepSecurity says the @cap-js packages were published after an attacker pushed changes that abused npm trusted publishing through GitHub Actions and OIDC. The details of that chain come from StepSecurity's research, so they should stay labeled as researcher-reported. But the broader point is already backed by SAP's own fix: a workflow that could publish automatically after the wrong push had too much authority.

That is the uncomfortable edge of "trusted publishing." Teams hear that phrase and think the hard part is over because long-lived tokens are gone. It helps, but it does not erase trust-boundary mistakes inside the repository and workflow that mint short-lived credentials. If a compromised account or unauthorized commit can still reach the publish job, the security model is weaker than the branding suggests.

The mbt side appears different. StepSecurity says that package did not use OIDC trusted publishing and instead relied on a static npm automation token. If that detail holds, the incident is even uglier because it shows two bad roads to the same destination: one path through old token-based publishing, another through over-trusted CI automation.

The editor persistence angle makes this nastier than a normal bad release

The credential theft is already serious. The persistence mechanism is the part that should bother anyone using AI coding tools or editor automation.

StepSecurity says the payload committed .vscode/tasks.json and .claude/settings.json changes into victim repositories so the malware could re-run when a project was opened in VS Code or Claude Code. GitGuardian separately described the campaign as self-replicating and said it observed stolen tokens creating public GitHub repositories used for exfiltration. That does not prove every claimed persistence detail in every repo. It does show the attack was not designed as a smash-and-grab.

This is what modern supply-chain abuse looks like when it grows up a little. The malware is no longer content to steal secrets from one laptop and leave. It wants the laptop, the repo, the CI runner, and the editor hooks around the repo.

What remains uncertain

Some parts of the story still need careful labels.

First, the deepest mechanics of the @cap-js OIDC abuse come from StepSecurity's analysis, not from an SAP postmortem. SAP's remediation PR supports the broad point that workflow publishing permissions were too open, but the exact attack chain is still researcher-reported.

Second, the package-version reporting is a little noisy across sources. Most sources align on @cap-js/postgres@2.2.2 and @cap-js/db-service@2.10.1, but one section of StepSecurity's post appears to swap those version numbers later in the article. That inconsistency does not change the existence of the compromise, but it is a reminder to treat fast-moving incident write-ups carefully.

Third, the public scope was still moving while researchers wrote. GitGuardian said repository counts tied to the campaign were rising in real time. In a story like this, exact victim counts age badly within hours.

What developers should do with this

The boring advice still matters. If these packages touched your environment, rotate GitHub, npm, and cloud credentials. Check repositories for unexpected .vscode/tasks.json or .claude/settings.json changes. Review recent workflow modifications, especially anything that affects release jobs or OIDC token use.

The less boring lesson is architectural. Treat package publishing as production access, whether it comes from a static token or a short-lived OIDC exchange. Gate release jobs. Limit which branches and workflows can mint registry credentials. Make publish approval an explicit step for high-value packages. If a single unauthorized push can turn CI into a package publisher, the problem is not just one compromised account. The problem is that the release path was trusted too broadly.

That is why this Reddit thread mattered. The headline was "SAP packages got popped." The real story is that software supply-chain trust now lives in the seams between registry accounts, CI identity, repository permissions, and developer tooling. Attackers know it. A lot of teams still act like those seams are somebody else's problem.

Sources