Poisoned Pipeline / Incidents / AS34
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
- T0113 Compromised user account
- T0166 Trigger pipeline execution
- T0202 Inadequate CI/CD workflow permissions
- T0121 Compromised legitimate artifact
- T0206 Forge or omit build provenance
- T0109 Publish malicious artifact
- T0159 Malicious artifact execution
supply-chain Maintainer repo and npm trusted publishing
Push to main on the real @dforge-core/dforge-mcp maintainer account.
Three-line change made any push to main start the release workflow.
Workflow rewritten to publish unattended; OIDC made push equal publish.
Version 0.2.21 of a real package, not a typosquat.
Provenance was valid and named the attacker's commit. Presence of
trusted-publishing attestation did not mean the commit was authorized.
0.2.21 was npm latest for 35 minutes.
One-line loader in indexe.cjs; implant deletes itself after run.
Framework gaps noted
- Honest provenance of a dishonest commit is still modeled as T0206 (forge or omit), which names the inverse failure mode.