forge-jsxy npm Infostealer: IOCs & Detection Guide

forge-jsxy: The npm Infostealer That Keeps Changing Its Name

TL;DR

For roughly two months, a single npm infostealer has resurfaced under a rotating series of package names while shipping a nearly unchanged payload. It began openly as forge-jsxy, spawned forge-jsx3 / forge-jsx4 siblings, then dropped the "forge" branding entirely to pose as developer infrastructure — first zredis-typed, and most recently pinokio-redis.

Every variant carries the same internal toolchain: files named forge-jsx-explorer-*, a relayPackageServe module that serves a forge-jsxy-package.tgz, and a durable runtime hidden under a dotted directory so it survives deletion of the npm package.

The payload reads cryptocurrency wallet material and developer credentials from the host and transmits them to Discord webhooks, HuggingFace Hub uploads, and a hardcoded C2 endpoint. It installs OS-level autostart so it runs again after reboot, and it captures clipboard, keyboard, and screen activity. The latest variant, pinokio-redis, describes itself as an "Autodesk Forge" integration — a description unrelated to what the code does.

Ecosystemnpm
Payload classmulti-stage infostealer + remote-control agent (RAT)
Primary targetscrypto wallets, browser wallet extensions, developer/cloud credentials
Persistencehidden durable runtime + OS autostart (survives package removal)
ExfiltrationDiscord webhooks + relay, HuggingFace Hub, hardcoded C2 on port 9877
Observed spanMay 2026 – July 2026 (ongoing)
Latest namepinokio-redis:1.0.127

Attack Anatomy

Every variant in this family installs through the same shape: a package that looks inert on its listing page but declares a postinstall hook, so the payload runs the moment the package is installed as a dependency. The hook drives a five-stage chain.

  • Stage 1 — materialize. The install script decodes a bundled, encoded blob into a set of runtime scripts and writes them into a hidden directory under the platform config location (the forge-jsxy versions used a dotted .forge-jsxy/runtime/v<version>/ path). Because this copy lives outside node_modules, removing or unpublishing the npm package does not remove the running agent.
  • Stage 2 — persist. The chain registers an OS autostart entry so the agent relaunches on reboot. On Windows this runs through a hidden PowerShell diagnostics script; the agent process is spawned detached and with windowsHide set so no console window appears.
  • Stage 3 — evade. The runtime checks for continuous-integration markers and quietly exits when it detects a CI environment, so automated build sandboxes see nothing. In the forge-jsxy versions, a source comment stated that a visible forgeInstall field was deliberately omitted from package.json “because that field would be visible on npm” — the operator kept the trigger metadata off the public listing on purpose.
  • Stage 4 — collect. Once running, the agent harvests, in one pass:
  1. Crypto wallet material. A bundled secret_filename_patterns.json  target list drives a filesystem sweep for wallet.dat, *.mnemonic /.seed / *.phrase files, keypair.json, Ethereum UTC– keystores, and *.p12 / *.pfx / *.jks key stores. Wallet-derivation libraries (bip39, secp256k1, base58check, and Solana helpers) are present in the bundle.
  2. Browser wallet extensions. A chromiumExtensionDbHarvest module  reads the local extension-storage databases of Chromium browsers, the location where browser-based wallet extensions keep their vault data.
  3. Credentials and secrets. The agent scans shell history and  secret-bearing files and reads developer/cloud credentials, then encodes HuggingFace credentials for upload.
  4. Live input. Clipboard contents, keyboard input, and screenshots are  captured on an ongoing basis.
  • Stage 5 — exfiltrate. Collected data leaves the host through three channels operating in parallel: Discord webhooks (discordWebhookPost) and a Discord relay uploader that talks to `discord.com/api/v10` (discordRelayUpload), HuggingFace Hub uploads (hfUpload), and a hardcoded C2 endpoint reached over port 9877. A relayPackageServe module additionally serves a forge-jsxy-package.tgz back out — the same artifact name across every rename.

The important structural point is that stages 1–3 run at install time with no user interaction, and stage 1 places the payload somewhere the package manager does not track. A developer who notices the odd dependency and runs npm uninstall removes the listing but not the agent.

The payload also resists a quick read. The runtime scripts are not shipped in the clear: an encode-deployment step keeps the operational logic as an encoded blob that only expands into readable scripts once the install chain decodes it into the hidden runtime directory. The files that are visible on the listing — the thin postinstall shim and a dist-materialization helper — reveal little about what ultimately runs. This encoded-delivery design has had a measurable effect on triage: across the family’s lifespan, multiple confirmed variants were scored safe by automated classification, and the payload has been opaque enough to stall automated review outright. The behaviors that give the family away are visible only after the encoded stage is expanded, and the runtime is read directly.

Timeline

The family’s payload has stayed remarkably stable; what changes is the name on the box. The arc runs from open “forge” branding toward disguises as unrelated developer tools.

Date (2026) Package : version Note
May (early) forge-jsxy:1.0.81, :1.0.90 Earliest confirmed variants — RAT with AES-256-GCM-encrypted C2
May 19 forge-jsxy:1.0.92 / 1.0.105 / 1.0.107 / 1.0.108 Campaign in active publishing; 1.0.92 was initially mislabeled safe and reversed on code re-review
Late May forge-jsx3 / forge-jsx4:1.0.122 / 1.0.123, zod-pino Sibling package names, same toolchain
Jun 4 forge-jsxy:1.0.120 Continuation; classified safe by the ML model (a miss)
Jun 21–23 forge-jsxy:1.0.121 Module set unchanged from 1.0.120
Jul 6 zredis-typed:1.0.127 "forge" dropped from the name; still ships forge-jsxy-package.tgz and forgeAgent* config keys
Jul 7 pinokio-redis:1.0.127 Same toolchain; new C2; describes itself as an "Autodesk Forge" integration

Two things stand out across the timeline. First, the version number 1.0.127 is reused verbatim by both zredis-typed and pinokio-redis — the naming shifts but the build lineage does not reset. Second, the shift away from “forge-*” names coincides with a shift toward names that read as ordinary infrastructure (redis, pinokio), lowering the chance a developer skims the name and hesitates.

Indicators of Compromise

IOCs below are defanged. The C2 host rotated between the forge-jsxy line and the latest variant while keeping the same port.

Indicator Value Seen in
C2 endpoint 212.193.3[.]61:9877 pinokio-redis:1.0.127
C2 endpoint 79.108.162[.]160:9877 forge-jsxy line, zredis-typed:1.0.127
Exfil channel discord.com/api/webhooks/… (webhook post) all variants
Exfil channel discord.com/api/v10 (relay upload) all variants
Exfil channel HuggingFace Hub upload all variants
Served artifact forge-jsxy-package.tgz (via relayPackageServe) all variants
Toolchain files chromiumExtensionDbHarvest, discordRelayUpload, discordWebhookPost, hfUpload, encode-hf-credentials, forge-jsx-explorer-* all variants
Target list secret_filename_patterns.json (wallet.dat, .mnemonic/.seed/.phrase, keypair.json, UTC--, .p12/.pfx/*.jks) all variants
Hidden runtime dotted …/.forge-jsxy/runtime/v<version>/ config-dir path forge-jsxy line
Windows persistence hidden PowerShell "forge diagnostics" autostart script all variants
Install trigger postinstall hook invoking a dist-materialization script chain all variants

The most durable detection signal is not any single host or webhook — those rotate — but the toolchain filenames and the forge-jsxy-package.tgz artifact, which have persisted verbatim through every rename.

Attribution & Observed Behavior

The packages were published under more than one npm account. The forge-jsxy line used the publisher jacksonkaandorp2 (jacksonkaandorp2@outlook[.]com); the latest pinokio-redis variant was published by donimique (donimiqueakers@gmail[.]com). Neither account carried a verified email or a linked source repository. The through-line across accounts is the toolchain, not the publisher identity — the same module names, the same served .tgz, and the same exfil design recur regardless of who published.

Several observable behaviors indicate deliberate concealment rather than accidental over-collection:

The runtime is placed outside node_modules in a hidden directory, so  it outlives the package that delivered it.

The agent bails out when it detects a CI environment, limiting exposure  in automated analysis sandboxes.

The agent process is launched detached and window-hidden.In the forge-jsxy versions, a comment tied the omission of a visible  install field to that field being “visible on npm.”

The public package descriptions are unrelated to the code — pinokio-redis  presents as an “Autodesk Forge” integration.

One recurring detection gap is worth noting for defenders relying on automated classification: multiple confirmed variants in this family were scored as safe by an ML classifier before code review corrected the verdict. The stable elements a reviewer can anchor on — the install-time chain, the hidden runtime, the toolchain filenames — are exactly the ones that survive the renames.

We describe the above as observed behavior. We do not attribute the campaign to any named actor, and we make no claim about the operator’s identity or objectives beyond what the code and infrastructure demonstrate.

Who is exposed. The collection set is squarely aimed at developer machines: cryptocurrency wallets and keystores, browser wallet extensions, shell history, and cloud/service credentials. Anyone who installs an affected package — directly or as a transitive dependency — during the window it was live is in scope, and the persistence design means the exposure does not end when the package is removed.

Why the persistence matters. Because stage 1 copies the payload into a hidden runtime directory and stage 2 registers autostart, the usual remediation instinct (uninstall the bad dependency, delete node_modules, reinstall) does not evict the agent. Incident response has to look for the out-of-tree runtime and the autostart entry, not just the package.

The trend. This family illustrates a pattern worth watching: a payload that is stable and mature, wrapped in a stream of disposablepackage names that migrate away from any name a prior takedown made recognizable, toward names that read as ordinary infrastructure. Name-based blocklists and publisher reputation age out quickly against this; behavior- and artifact-based signals do not.

For developers and consumers

Treat install-time scripts as the primary risk surface. Install with  scripts disabled where feasible and review any dependency that declares a postinstall. Pin and vet transitive dependencies; this class of malware arrives as  easily through a sub-dependency as a direct one.

On a suspected host, hunt beyond the package: look for a hidden runtime  directory in the platform config location, an unexpected autostart entry, and outbound connections to Discord webhook or :9877 endpoints.

Assume any wallet seed phrase, keystore, or credential present on an  affected host during the exposure window is compromised, and rotate.

For registries and defenders

Alert on the durable artifacts (forge-jsxy-package.tgz, the  forge-jsx-explorer-* / chromiumExtensionDbHarvest / discordRelayUpload filenames) rather than the package name, which changes.

Flag the structural combination the family relies on — a postinstall  that materializes scripts into a hidden config-dir path plus an OS autostart registration — independent of the specific strings involved.

The name on the package has changed at least four times; the crate inside has not. Detection built on what the code does has outlasted every relabeling so far.

sca-tools-software-composition-analysis-tools
Prioritize, remediate, and secure your software risks
Get your Free Account.
No credit card required.

Secure your Software Development and Delivery

with Xygeni Product Suite