GHAPPIER Loader: npm Trusted-Publishing Abuse Compromises @dforge-core/dforge-mcp

GHAPPIER Loader (TL-2026-2605), also tracked as GHAPPIER, is a high-severity supply-chain compromise, first published 2026-09-21. It is attributed to PolinRider (North Korea) with low confidence, affects dforge-core (npm) @dforge-core/dforge-mcp, maps to 10 MITRE ATT&CK techniques (T1027, T1059.007, T1070.004), and is covered by 9 detection rules and 21 indicators of compromise.

Key facts for TL-2026-2605

Threat ID
TL-2026-2605
Also known as
GHAPPIER, dforge-mcp npm Trusted-Publishing Compromise, PolinRider-linked npm Loader Incident
Severity
HIGH
Status
ACTIVE
Category
SUPPLY_CHAIN
First published
2026-09-21
Last reviewed
2026-09-21
Attribution
PolinRider
Attribution confidence
LOW
Nation-state nexus
North Korea
Motivation
FINANCIAL
Target sectors
software development, technology, cryptocurrency, open source supply chain
Target regions
Global
Detection rules
9
Indicators of compromise
21

Malware and tooling in GHAPPIER Loader

Malware and tooling: BeaverTail - S1246, DEV#POPPER, InvisibleFerret - S1245, OmniStealer, core, 0x3f0e5781d0855fb460661ac63257376db1941b2bb522499e4757ecb3ebd5dce3, 0xbe037400670fbf1c32364f762975908dc43eeb38759263e7dfcdabc76380811e, TMfKQEd7TJJa5xNZJZ2Lep838vrzrs7mAP, TXfxHUet9pJVU1BgVkBAbrES4YUc1nGzcG

An attacker compromised the maintainer account of the npm package @dforge-core/dforge-mcp and abused GitHub Actions OIDC trusted publishing and Sigstore attestation to ship trojanized versions 0.2.20 and 0.2.21, delivering a previously unreported four-stage, self-deleting loader (GHAPPIER) that opens a remote shell when the MCP server launches. CloudSEK links a second payload family to the DPRK-linked PolinRider campaign, active since March 2026 across 65+ repositories, 73 files, and 22 accounts.

How GHAPPIER Loader works

On September 9, 2026, an unidentified attacker gained control of the maintainer account for the npm package @dforge-core/dforge-mcp — a legitimate Model Context Protocol (MCP) server exposing 34 tools that let AI coding agents (Claude Code, Cursor, Zed) scaffold, build, and ship dForge modules — for a window of 105 minutes. CloudSEK's investigation found the attacker already held push access to the package's main branch at the start of the intrusion and assesses the likely root cause as a developer workstation infected by a malicious extension or package, though the initial infection vector itself remains unconfirmed. Using that access, the attacker modified the GitHub Actions release workflow (a three-line change to trigger release on any push to main), then 14 minutes later rewrote the workflow again to make publishing fully unattended. Two trojanized releases followed: version 0.2.20, which failed to become the active release, and version 0.2.21, which published successfully with valid npm provenance and a Sigstore attestation and remained the registry's 'latest' tag for 35 minutes 38 seconds before the legitimate maintainer reverted the account and shipped a clean 0.2.22.

Version 0.2.21 carried a single-line loader — dubbed GHAPPIER by CloudSEK — embedded at line 3,320 of an otherwise-unremarkable 99KB file. The loader does not execute on install; it fires only when the MCP server process is actually launched, meaning any environment that merely installed 0.2.21 as a dependency without starting the server was never compromised. Once triggered, GHAPPIER runs as a four-stage progression culminating in a general-purpose remote shell; the final-stage implant then deletes itself from disk the moment it finishes executing, removing the on-disk artifact while, per CloudSEK, remaining live and responsive for at least five days after the compromised account was recovered. CloudSEK frames the incident as an authorization-chain failure rather than a code-signing break: 'every action in this report is an authorised action taken with a stolen key' — npm/Sigstore provenance attests where an artifact was built, not whether the commit that triggered the build was honest, and the fraudulent attestation remains permanently visible in Sigstore's public transparency log, which is how the attacker's commit was ultimately identified.

CloudSEK ties a second payload family observed in the same investigation to PolinRider, a DPRK-linked loader/credential-harvesting campaign that OpenSourceMalware has tracked since March 2026 and which by CloudSEK's count now spans 65+ public repositories, 73 infected files, and 22 compromised accounts. CloudSEK reports that payload family reads its runtime configuration from empty Ethereum transactions (roughly $0.20 each), a blockchain dead-drop-resolver pattern consistent with PolinRider's documented use of TRON, Aptos, and BNB Smart Chain RPC endpoints elsewhere in the campaign. Attribution is contested: The Hacker News, Rescana, and OpenSourceMalware attribute the broader PolinRider/'Contagious Interview' cluster to North Korea's Lazarus Group and APT37 (ScarCruft) with high confidence, but CloudSEK states its own independent verification of the North Korea linkage for this specific incident was inconclusive — this research therefore records the actor as the PolinRider cluster with LOW attribution confidence pending corroboration. The campaign's other confirmed activity — a June 2026 Sonatype-tracked compromise of the unrelated npm package @common-stack/generate-plugin across 13 versions using the same 'rmcej%otb%' obfuscation decoder seed, widespread injection of obfuscated JavaScript into config files such as postcss.config.mjs, tailwind.config.js, and eslint.config.mjs, VS Code .vscode/tasks.json runOn:'folderOpen' auto-execution abuse, and anti-dated git-history rewriting — illustrates PolinRider's broader tradecraft, though none of those specific artifacts were confirmed present in the dforge-mcp compromise itself.

CloudSEK found no evidence of successful downstream organizational compromise and no exploitation of GitHub- or npm-platform vulnerabilities — the entire chain rode on a single stolen credential plus the trust normally placed in provenance attestation. As of the report date, no CVE had been assigned and no advisory existed in OSV or the GitHub Advisory Database for @dforge-core/dforge-mcp. Because this is the first confirmed abuse of npm trusted-publishing/OIDC to smuggle a working remote-access implant into an AI-agent tool's supply chain, and because the affected package sits directly in the MCP tool-installation path for Claude Code, Cursor, and Zed users, the incident is significant beyond its narrow, contained blast radius. CloudSEK's recommended defense — treating unexpected release-workflow modifications and multi-stage artifact patterns as the detection signal, rather than attempting to signature the self-deleting implant itself — reflects that provenance attestation alone is an insufficient trust boundary.

MITRE ATT&CK techniques used in TL-2026-2605

Defense Evasion

T1027 Obfuscated Files or Information; T1070.004 File Deletion

Execution

T1059.007 JavaScript

Command and Control

T1071.001 Web Protocols; T1102.001 Dead Drop Resolver

Initial Access

T1078 Valid Accounts; T1195.002 Compromise Software Supply Chain

Credential Access

T1552.001 Credentials In Files; T1555.003 Credentials from Web Browsers

Resource Development

T1608.001 Upload Malware

Affected products and versions in GHAPPIER Loader

  • dforge-core (npm) — @dforge-core/dforge-mcp
    Vulnerable versions: 0.2.20; 0.2.21
    Fixed in: 0.2.22
  • common-stack (npm) — @common-stack/generate-plugin
    Vulnerable versions: 9.0.2-alpha.21; 9.0.2-alpha.22; and 11 further compromised 9.0.2-alpha.x releases per Sonatype-2026-003277
    Fixed in: version preceding the compromised 9.0.2-alpha.x series

Remediation for GHAPPIER Loader

Patches

  • Upgrade @dforge-core/dforge-mcp to 0.2.22 or later.

Immediate actions

  • If any environment installed @dforge-core/dforge-mcp 0.2.20 or 0.2.21 AND launched the MCP server, treat the host as compromised: isolate it and rotate all credentials/API keys reachable from that host, since the implant deletes its on-disk artifact but may remain active.
  • Pin @dforge-core/dforge-mcp to 0.2.22 or later and audit lockfiles across all repositories for any reference to 0.2.20 or 0.2.21.
  • Audit GitHub Actions release-workflow history for packages you maintain for unauthorized edits that convert manual/reviewed publishing into unattended publishing triggered on push.
  • Review the npm/Sigstore public transparency log for unexpected provenance attestations tied to your maintainers' commits.

Workarounds

  • Do not launch the MCP server from any install that resolved 0.2.20 or 0.2.21 until node_modules is wiped and reinstalled against a pinned safe version.

Longer-term hardening

  • Require branch protection and mandatory review on workflow files (.github/workflows/*) that can trigger a trusted-publishing release, not just on application source code.
  • Do not treat npm/Sigstore provenance attestation alone as a trust signal — it attests where an artifact was built, not whether the triggering commit was honest; pair it with commit-review and anomaly-monitoring policy.
  • Monitor for outbound connections from developer and CI environments to blockchain RPC endpoints (Ethereum, TRON, Aptos, BNB Smart Chain), a documented PolinRider dead-drop C2 pattern.
  • Adopt supply-chain scanning (Socket.dev, OSV-Scanner, npm audit signatures) against the growing PolinRider package/version indicator set and monitor for multi-stage artifact patterns rather than relying on implant signatures alone.

Weaknesses (CWE) in GHAPPIER Loader

CWE-506, CWE-829

Timeline of GHAPPIER Loader

  • OpenSourceMalware first publicly discloses tracking of the PolinRider campaign, reporting roughly 675 compromised GitHub repositories tied to obfuscated JavaScript loaders and anti-dated commits.
  • PolinRider activity expands to 1,951 compromised public GitHub repositories across 1,047 unique owners, including a merge broadening the VS Code auto-run-task ('TasksJacker') abuse technique.
  • Sonatype (advisory Sonatype-2026-003277) reports a separate PolinRider-linked npm compromise of @common-stack/generate-plugin across 13 malicious 9.0.2-alpha.x releases, using the same 'rmcej%otb%' obfuscation decoder seed and blockchain-sourced (Tron) payload retrieval later linked to this campaign family.
  • GitHub account 'Xpos587' is taken over and used to push bulk malicious commits across Go modules as part of PolinRider's cross-ecosystem expansion.
  • The Hacker News reports North Korea-linked actors have published 108 malicious packages/extensions (162 malicious release artifacts) across npm, Packagist, Go modules, and the Chrome Web Store as part of the PolinRider/'Contagious Interview' cluster.
  • Trojanized version 0.2.21 is published with valid npm provenance and Sigstore attestation and remains the latest release for 35 minutes 38 seconds before the legitimate maintainer reverts the account and publishes clean version 0.2.22.
  • Trojanized version 0.2.20 of @dforge-core/dforge-mcp is published via the abused GitHub Actions OIDC trusted-publishing pipeline but fails to become the active/latest release.
  • An attacker gains access to the @dforge-core/dforge-mcp npm maintainer's GitHub account for 105 minutes and modifies the release workflow to trigger unattended publishing on pushes to main.
  • CloudSEK publishes its GHAPPIER analysis, identifying the four-stage self-deleting loader across 65+ repositories, 73 infected files, and 22 accounts, and linking a second payload family to the DPRK-linked PolinRider campaign.
  • Infosecurity Magazine publishes coverage of the CloudSEK findings, bringing the dforge-mcp trusted-publishing abuse incident to wider public attention.

Sources cited for GHAPPIER Loader

More in supply chain

Detection coverage for TL-2026-2605

As of 2026-09-21, Threadlinqs Intelligence publishes 9 detection rule(s) for TL-2026-2605 across Splunk SPL, Microsoft KQL and Sigma, covering 21 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.

Further reading

Threadlinqs Intelligence — Real-Time Threat Detection Platform

[ 0 threats ] [ 0 det ] [ CRIT: 0 ] [ HIGH: 0 ]
// threat_feed
$ sort --newest
Showing all threats

Latest Threats