Poisoned Pipeline

Poisoned Pipeline / Incidents / AS34

AS34 · 2026-09

GHAPPIER loader via @dforge-core/dforge-mcp trusted publishing

npmMCPGit / GitHubGitHub Actions

CloudSEK documented a 105-minute window on 9 September 2026 in which
someone with push access to the maintainer account of the legitimate npm
package @dforge-core/dforge-mcp added a remote-code loader, changed three
lines so any push to main started the release workflow, rewrote that
workflow 14 minutes later to publish unattended, and shipped 0.2.21.
The release sat as npm latest for 35 minutes 38 seconds before the
maintainer published a clean 0.2.22. The malicious version carried valid
npm provenance: GitHub Actions OIDC trusted publishing, with the
attacker's commit still in Sigstore. Provenance attested where the
artefact was built, not that the source was honest. The payload is one
line in a 99 KB working JS file (indexe.cjs); later stages delete
themselves from disk. CloudSEK tied a second payload family in another
victim repo to PolinRider (EtherHiding / NullReceiver). No OSV or GHSA
advisory was published. How the maintainer push access was obtained is
not established.

Mapped techniques

supply-chain Maintainer repo and npm trusted publishing

T0113 · Initial Access · Compromised user account

Push to main on the real @dforge-core/dforge-mcp maintainer account.

T0166 · Execution · Trigger pipeline execution

Three-line change made any push to main start the release workflow.

T0202 · Persistence · Inadequate CI/CD workflow permissions

Workflow rewritten to publish unattended; OIDC made push equal publish.

T0121 · Resource Development · Compromised legitimate artifact

Version 0.2.21 of a real package, not a typosquat.

T0206 · Defense Evasion · Forge or omit build provenance

Provenance was valid and named the attacker's commit. Presence of
trusted-publishing attestation did not mean the commit was authorized.

T0109 · Resource Development · Publish malicious artifact

0.2.21 was npm latest for 35 minutes.

T0159 · Execution · Malicious artifact execution

One-line loader in indexe.cjs; implant deletes itself after run.

Framework gaps noted

Sources