GHAPPIER Loader: npm Supply-Chain Compromise of @dforge-core/dforge-mcp Linked to DPRK PolinRider Campaign
GHAPPIER Loader (TL-2026-2588), also tracked as GHAPPIER, is a high-severity supply-chain compromise, first published 2026-09-20. It is attributed to PolinRider (North Korea) with low confidence, affects dforge-core @dforge-core/dforge-mcp (npm package), maps to 14 MITRE ATT&CK techniques (T1027, T1059.007, T1070.004), and is covered by 9 detection rules and 24 indicators of compromise.
Key facts for TL-2026-2588
- Threat ID
- TL-2026-2588
- Also known as
- GHAPPIER
- Severity
- HIGH
- Status
- ACTIVE
- Category
- SUPPLY_CHAIN
- First published
- 2026-09-20
- Last reviewed
- 2026-09-20
- Attribution
- PolinRider
- Attribution confidence
- LOW
- Nation-state nexus
- North Korea
- Motivation
- FINANCIAL
- Target sectors
- software-development, technology, open-source-supply-chain, cryptocurrency
- Target regions
- Global
- Detection rules
- 9
- Indicators of compromise
- 24
Malware and tooling in GHAPPIER Loader
Malware and tooling: BeaverTail - S1246, DEV#POPPER, GHAPPIER, OmniStealer, PolinRider, core, 0xa322e5f3d311d3080e6f0121063e9adc2490ef1a, 0xa658863ea658863e68656c6c6f6970626f742121, 0xbe037400670fbf1c32364f762975908dc43eeb38759263e7dfcdabc76380811e, NullReceiver, TMfKQEd7TJJa5xNZJZ2Lep838vrzrs7mAP, TXfxHUet9pJVU1BgVkBAbrES4YUc1nGzcG
CloudSEK identified GHAPPIER, a previously unreported four-stage loader delivered through a 105-minute maintainer-account takeover of the npm package @dforge-core/dforge-mcp (malicious v0.2.21, reverted to clean v0.2.22). The malicious release carried valid npm provenance via abused GitHub Actions OIDC trusted publishing, used an Ethereum-blockchain address as its command source, and self-deleted its final implant. Payload and infrastructure overlap ties GHAPPIER to the DPRK-linked PolinRider campaign, which has separately compromised 65+ npm/GitHub repositories in this incident and, cumulatively since March 2026, thousands of repositories across npm, PyPI, Go, Packagist, and Chrome Web Store.
How GHAPPIER Loader works
On 2026-09-09, an attacker held valid push/publish-equivalent access to the @dforge-core/dforge-mcp npm maintainer account for a 105-minute window. Fourteen minutes into that window the GitHub Actions CI workflow was rewritten to auto-publish on push to main without manual review, and a remote-code loader was injected as a single line (line 3320 of a 99KB configuration file) into otherwise-legitimate package source. Version 0.2.21 reached the npm registry and remained the latest release for 35 minutes 38 seconds before the maintainer reverted the account and published a clean v0.2.22. Because the malicious release was built through the repository's legitimate GitHub Actions OIDC trusted-publishing workflow, it carried a genuine npm provenance statement and an authentic Sigstore attestation naming the attacker's own commit -- CloudSEK's central finding is that provenance attests where an artefact was built, not whether its source was honest, so trusted publishing let a single compromised push credential produce a fully 'verified' malicious release.
The payload is a four-stage loader: an initial injected loader in package source, a rewritten CI workflow that forces unattended publishing, the published malicious package itself, and a final implant that deletes itself from disk the instant it executes, leaving no artefact for a post-incident file sweep to find. Instead of a traditional domain- or IP-based C2 channel, the PolinRider-linked payload reads its command source from an Ethereum blockchain wallet address: a twenty-byte recipient address is embedded in an otherwise-empty transaction costing roughly $0.20, giving the operator a C2 channel with no domain to suspend, no host to seize, and no account to disable. CloudSEK reports one socket endpoint and two delivery hostnames tied to the campaign (values withheld from the public blog behind a gated full report) and states that an exact-match sample of the payload was still beaconing as the report was being written, more than five days after the malicious npm version was withdrawn.
This blockchain dead-drop design mirrors -- and CloudSEK cites payload/infrastructure overlap with -- the DPRK-linked PolinRider campaign, tracked publicly since March 2026, which has grown from 675 to over 1,900 GitHub repositories by April 2026 and, per subsequent reporting, expanded across npm, PyPI, Go modules, Packagist, and a Chrome extension (108-111 unique packages, ~160-200 release artifacts) by July 2026, with a further compromised high-download Packagist package (visanduma/nova-two-factor, 700,000+ downloads) disclosed by Socket on 2026-09-17, three days before the GHAPPIER report. PolinRider's own blockchain C2 uses TRON and Aptos (with BNB Smart Chain observed) dead-drop addresses to fetch XOR-encrypted second-stage payloads executed via eval(), delivering RATs and infostealers (DEV#POPPER, OmniStealer) and, per OpenSourceMalware, a variant of the DPRK Beavertail malware family. A closely related technique named NullReceiver (published August 2026) encodes a C2 IP directly in the recipient-address bytes of an Ethereum wallet's most recent outbound transaction -- the same 'address-as-C2' primitive GHAPPIER's payload uses -- and was found in separate npm packages (bianira-ui, fluid-type-ui) tied to the same DPRK developer-targeting cluster (Contagious Interview / Famous Chollima).
CloudSEK is explicit that its North Korea attribution is inherited from NullReceiver researchers rather than independently re-verified, and that 'nothing here evidences a successful compromise of any organisation' downstream of the npm package -- the incident documents a successful supply-chain injection and a live, still-functional payload, not confirmed victim compromise. Because the final implant self-deletes, CloudSEK recommends defenders sweep for the artefacts the chain leaves behind (a rewritten CI workflow, the injected loader line, transient blockchain-RPC network connections) rather than searching for the implant file itself, which will not be there to find.
MITRE ATT&CK techniques used in TL-2026-2588
Defense Evasion
T1027 Obfuscated Files or Information; T1070.004 File Deletion; T1140 Deobfuscate/Decode Files or Information
Execution
Command and Control
T1071.001 Web Protocols; T1102.002 Bidirectional Communication
Initial Access
T1078 Valid Accounts; T1195.002 Compromise Software Supply Chain; T1199 Trusted Relationship
Credential Access
T1552.001 Credentials In Files
Resource Development
T1583.001 Domains; T1585 Establish Accounts; T1587.001 Malware; T1608 Stage Capabilities
Affected products and versions in GHAPPIER Loader
- dforge-core — @dforge-core/dforge-mcp (npm package)
Vulnerable versions: 0.2.21
Fixed in: 0.2.22
Remediation for GHAPPIER Loader
Patches
- Upgrade @dforge-core/dforge-mcp to v0.2.22, the clean release the maintainer published immediately after revoking attacker access
Immediate actions
- Audit npm installs and lockfiles for @dforge-core/dforge-mcp version 0.2.21; pin/upgrade to 0.2.22 or later
- Block CloudSEK's identified delivery hostnames and socket endpoint at network egress once the full report's IOC list is obtained
- Rotate any credentials (git, npm, CI secrets) that were active on developer or CI systems during or after the 2026-09-09 105-minute compromise window
- Audit GitHub Actions workflow files across trusted-publishing-enabled repositories for unauthorized auto-publish or auto-execute modifications
Workarounds
- Sweep for the artefacts the four-stage chain leaves behind (rewritten workflow files, the injected loader line, transient blockchain-RPC connections) rather than for the self-deleting final implant, which leaves no file on disk to find
Longer-term hardening
- Do not treat npm provenance or Sigstore attestation as a proxy for source-code integrity -- provenance proves where an artefact was built, not that its source was honest
- Require branch protection and mandatory code review on any branch wired to a trusted-publishing OIDC workflow so a single compromised push credential cannot trigger an unreviewed publish
- Monitor build and developer-environment egress for connections to public blockchain RPC endpoints (Ethereum/TRON/Aptos/BSC) as a dead-drop-resolver C2 detection signal
- Apply install-time behavioral scanning and SBOM tracking to MCP/AI-developer-tooling npm dependencies given active DPRK targeting of the AI tooling supply chain
Timeline of GHAPPIER Loader
- Earliest known PolinRider tradecraft observed retroactively: anti-dated commits later found in compromised Packagist repositories.
- OpenSourceMalware publishes the first public PolinRider analysis, documenting 675 infected GitHub repositories across 352 owners.
- PolinRider rotates its JavaScript obfuscator variant (marker 'Cot%3t=shtP') in apparent evasion of published YARA rules.
- PolinRider's documented footprint reaches 1,951 repositories across 1,047 owners, a 2.9x growth in five weeks.
- The Visanduma GitHub organization's repositories, including the 700,000+ download visanduma/nova-two-factor Packagist package, are compromised via the LaHiRu developer account (disclosed later by Socket).
- An account takeover triggers bulk compromise of Go modules resolving directly from compromised Git repositories, around 10:00 UTC.
- TheHackerNews reports North Korean-linked actors have published 108 unique malicious packages (162 release artifacts) across npm, Packagist, Go modules, and a Chrome extension, confirming cross-ecosystem spread.
- OpenSourceMalware reports PolinRider's blockchain second stage (TRON/Aptos/BSC) now delivers the DEV#POPPER RAT and OmniStealer infostealer.
- Researchers (credited by CloudSEK as the source of DPRK attribution) publish the NullReceiver technique: decoding a C2 IP from the recipient-address bytes of a DPRK-controlled Ethereum wallet's most recent outbound transaction.
- The maintainer reverts the compromised account and publishes clean version 0.2.22, ending the 105-minute exposure window.
- Fourteen minutes into the compromise window the GitHub Actions CI workflow is rewritten to auto-publish on push to main, the GHAPPIER loader is injected as a single line into package source, and malicious version 0.2.21 is published to npm with valid OIDC provenance and Sigstore attestation, remaining live for 35 minutes 38 seconds.
- An attacker gains a 105-minute window of push/publish-equivalent access to the @dforge-core/dforge-mcp npm maintainer account.
- Five or more days after the malicious npm version's withdrawal, all four GHAPPIER loader stages remain functional when tested.
- Socket discloses the visanduma/nova-two-factor Packagist compromise, describing PolinRider's continued spread via compromised GitHub accounts.
- CloudSEK publishes the GHAPPIER research, citing payload and infrastructure overlap with PolinRider and noting an exact-match sample was still beaconing as the report was written.
Sources cited for GHAPPIER Loader
- GHAPPIER - One loader, sixty-five repositories, twenty-two accounts: an unreported loader family beside DPRK's PolinRider campaign
- PolinRider (technical dossier)
- PolinRider Campaign: DPRK-Linked Supply Chain Attack Infects GitHub Repositories
- Trojanized npm Packages Employ NullReceiver Tactic to Decode C2 IP from Blockchain
- NullReceiver's Blank Crypto Transfers Solves the Challenges of EtherHiding
- North Korean Hackers Publish 108 Malicious Packages and Extensions in PolinRider Campaign
- PolinRider Jumps the Fence to Go, Packagist, npm, PyPI
- PolinRider Spreads Through Compromised GitHub Accounts and Packagist
- Week 38 - 2026 digest (GHAPPIER / PolinRider roundup)
- dforge-core/dforge-mcp (legitimate upstream repository)
More in supply chain
- GHAPPIER Loader: npm Trusted-Publishing Abuse Compromises @dforge-core/dforge-mcp
- Rust Team Members and Popular Crate Owners Targeted via Fake Job Video Calls (North Korea-Linked)
- indexed-btree npm Campaign: Runtime-Triggered Loader Evades Install-Script Defenses via BTree.prototype.set()
- Brevo Supply-Chain Attack: Stolen Cloudflare API Key Deploys Malicious Edge Worker, Backdoors 100,000+ Websites via ClickFix and a Rogue WordPress Plugin
- PhantomRaven: LLM-Generated npm Information Stealer Used for Bug Bounty Hunting
Detection coverage for TL-2026-2588
As of 2026-09-20, Threadlinqs Intelligence publishes 9 detection rule(s) for TL-2026-2588 across Splunk SPL, Microsoft KQL and Sigma, covering 24 indicator(s) of compromise. The whole corpus is readable without an account; a free account unlocks full detection query text in Splunk SPL, Microsoft KQL and Sigma; paid tiers add raw indicator values, correlation and the MCP server. Threadlinqs MCP server · View plans.
Community OSINT corroboration for TL-2026-2588
1 of this threat's indicators have also been reported by the open-source security community, which observed at least one of them before this report was published. Community sightings are unverified and are kept separate from Threadlinqs' curated indicators. Indicator values, reporters and campaign linkage are available to authenticated Red-tier users.