Attackers Abuse npm Trusted Publishing in GHAPPIER Campaign

Written by

Attackers have abused npm trusted publishing in a supply chain attack that shipped a previously unreported loader, GHAPPIER, in a legitimate package whose malicious release carried valid provenance.

In a report published on September 20, CloudSEK said someone used the maintainer account of @dforge-core/dforge-mcp for 105 minutes on September 9. A first malicious release, 0.2.20, failed and broke installation of the package, before 0.2.21 shipped the loader and stayed the latest version for 35 minutes and 38 seconds.

The attacker could already push to the main branch. CloudSEK said it could not establish how, but suspects a developer machine infected by a malicious extension or package.

Valid Provenance, Dishonest Source

The attacker changed three lines so any push to the main branch started the release workflow, then rewrote the workflow 14 minutes later so it could publish unattended. The build ran through GitHub Actions with OIDC trusted publishing, and its attestation is still in Sigstore's public log, naming the attacker's commit.

"Provenance attests where an artefact was built, not whether its source was honest," CloudSEK said. Because the registry trusts the repository's CI identity, push access was publish access, and the release would pass npm audit signatures.

The loader was one line in a 99KB file, opening a four-stage chain that ended in a general-purpose remote shell which deleted itself from disk as it ran. It fired when the MCP server was launched rather than on install, so systems that installed 0.2.21 without starting it did not run the loader.

CloudSEK found no exploitation of GitHub, npm or any package. "Every action in this report is an authorised action taken with a stolen key," it said.

Read more on npm supply chain attacks: Attackers Hijack Red Hat npm Scope to Steal Cloud Secrets

Linked to PolinRider, DPRK Unconfirmed

CloudSEK traced GHAPPIER across at least 65 public repositories, 73 infected files and 22 accounts. A second payload in another victim's repository exactly matched PolinRider, a campaign OpenSourceMalware has tracked since March 2026.

That payload read its configuration from an empty Ethereum transaction costing about $0.20, leaving no domain to suspend or host to seize. Other researchers attribute PolinRider to North Korea, but CloudSEK said its one independent check did not confirm it.

CloudSEK said PolinRider's documented credential harvesting is the likeliest route into the maintainer account. It found no evidence of a successful compromise of any organization.

As of the report, no advisory had appeared in OSV, the GitHub database or from the maintainer, though every stage still responded five days after the withdrawal.

CloudSEK advised pinning the package at 0.2.22, treating any lockfile that pins 0.2.21 as an indicator in itself, and sweeping for the artifacts the chain leaves rather than the implant. It also recommended alerting on changes to a release workflow's trigger block, which here came 14 minutes before the workflow could publish.

What’s Hot on Infosecurity Magazine?