Feed
HighPublished 27 Jun 2026Updated 29 Jun 20262 packages · 4 versions

`chai-as-persisted` + `chai-as-assured` — jsonspack DPRK campaign restarts with chai-as-* typosquat install-time RCE dropper

Summary

On 2026-06-26 → 2026-06-28 the same DPRK-linked operator behind the March jsonspack npm campaign restarted with chai-as-persisted and chai-as-assured — typosquats of chai-as-promised that ship install-time RCE droppers. Four versions across the two packages were published with the same hello@jsonspack.com author bug URL, fetching attacker JavaScript from ipregionchecker.org via new Function.constructor on every npm install.

typosquatcredential-theftcrypto-wallet-draininfostealerobfuscation
Threat actor
jsonspack DPRK cluster
Detected by
CIRCL / Vulnerability-Lookup · Panther (historical attribution)
Also known as
jsonspack wave 2 · chai-as-* June 2026 restart · chai-as-assured / chai-as-persisted cluster
Ecosystems
npm
Packages tracked
2

What happened

On 2026-06-27 between 01:41 UTC and 02:27 UTC, a previously-known DPRK-linked operator published two versions of chai-as-persisted to npm: 4.2.8 (created 01:41:12 UTC) and 6.1.9 (created 02:27:14 UTC). On 2026-06-26 17:02 UTC the same operator first staged chai-as-assured@7.1.2 — a clean fork of the legitimate chai-as-promised metadata (preserving Domenic Denicola as author) to gauge surface-level detection — then on 2026-06-28 17:17 UTC published the malicious chai-as-assured@6.0.4 with the same hello@jsonspack.com author contact, the https://jsonspack.com/issues bugs.url, the same smoke:pino / smoke:file script shell, and the same axios + parse-json + request + sqlite3 dependency triad. The maintainer for chai-as-assured (markheys3939 / markheys.eth@outlook.com) is distinct from chai-as-persisted (diazavasvu195), matching the jsonspack tradecraft of rotating outlook.com publisher accounts while the package.json author email (hello@jsonspack.com) and bug URL stay constant across the cluster. All four versions are typosquats of the widely-used chai-as-promised test-assertion library and are flagged by CIRCL / vulnerability-lookup (MAL-2026-6544 for chai-as-persisted). The package description ("This library/document describes the management of vulnerabilities for the project and all modules within the organization") and keywords (fast, logger, stream, json) are deliberately misleading — the shipped code masquerades as a Pino-style logger middleware to defeat surface-level review.

Install-time RCE chain

The package.json declares "postinstall": "npm run smoke:pino", where smoke:pino resolves to node ./index.js. index.js spawns a detached node lib/initializeCaller.js child via child_process and immediately child.unref()s it so execution survives npm install returning. initializeCaller.js hides the C2 URL inside base64 strings stored on a fabricated local process.env object using bait keys DEV_API_KEY, DEV_SECRET_KEY, DEV_SECRET_VALUE — defeating trivial string scanners that grep for the URL or for atob.

At run time it atob()-decodes the URL to https://www.ipregionchecker.org/api/ip-check-encrypted/3aeb34a37, POSTs to it via axios (declared as a dependency alongside parse-json), and passes the response body to new Function.constructor("require", response) — invoking it with the live require binding so the second-stage payload has full Node module access on the installer's machine.

Continuation of the jsonspack DPRK campaign

Panther first documented the jsonspack campaign on 2026-04-03 as 27 confirmed malicious npm packages published by eight distinct email accounts between 2026-03-18 and 2026-03-31, all sharing hello@jsonspack[.]com as the package.json author email. Attribution to a DPRK cluster overlapping Lazarus / Famous Chollima was driven by independent confirmation from the kmsec.uk DPRK npm threat-intelligence feed, which independently identified 24 of the 27 packages as part of a broader 163-package operation. chai-as-persisted re-uses the same author contact (hello@jsonspack.com, with bugs.url set to https://jsonspack.com/issues), the same chai-as-* typosquat naming convention, and the same Pino-impersonation masquerade — strong evidence the same operator has resumed publication three months after the original wave subsided.

The npm install-time exfiltration pattern, the use of Function.constructor for staged second-stage execution, and the deliberate string obfuscation are all consistent with the loader architecture Panther reverse-engineered in the original jsonspack cluster. The motivation in that cluster was crypto-wallet theft and credential exfiltration via a 40-wallet browser-extension targeting list, Brave browser emphasis, and 1-second-poll clipboard interception — the financial-targeting priorities consistent with DPRK operations.

Disclosure timeline

  • 2026-06-27 01:41:12 UTCchai-as-persisted@4.2.8 published by diazavasvu195.
  • 2026-06-26 17:02:41 UTCchai-as-assured@7.1.2 published as a clean fork preserving the legitimate chai-as-promised author metadata (Domenic Denicola).
  • 2026-06-27 01:41:12 UTCchai-as-persisted@4.2.8 published by diazavasvu195.
  • 2026-06-27 02:27:14 UTCchai-as-persisted@6.1.9 published (the high version jump from 4.x to 6.x makes the package look more mature than 46 minutes old).
  • 2026-06-27 — CIRCL / vulnerability-lookup publishes MAL-2026-6544 flagging both chai-as-persisted versions as deliberate install-time RCE droppers.
  • 2026-06-28 17:17:42 UTCchai-as-assured@6.0.4 published by markheys3939, this time with the hello@jsonspack.com author email, https://jsonspack.com/issues bugs.url, and smoke:pino / smoke:file scripts that mirror the chai-as-persisted jsonspack template.
  • As of 2026-06-29 — all four versions remain live on npm; no 0.0.1-security holder has replaced latest on either package.

Affected packages (2)

  • npmchai-as-assured
    7.1.26.0.4
  • npmchai-as-persisted
    4.2.86.1.9

Impact

  • Install-time arbitrary code execution: a postinstall script spawns a detached Node child that fetches attacker JavaScript from ipregionchecker.org and evaluates it via new Function.constructor('require', response) — full Node module access on the installer's machine, persisting after npm install returns via child.unref()
  • --ignore-scripts is the only flag that prevents detonation — the malicious code never runs from import/require of the package
  • Continuation of the jsonspack DPRK supply-chain campaign Panther first documented in March–April 2026 (27 confirmed packages from 2026-03-18 to 2026-03-31, attributed to a DPRK cluster overlapping Lazarus / Famous Chollima); the same hello@jsonspack.com author contact and chai-as-* typosquat naming pattern resurface here three months later
  • Likely follow-on credential and crypto-wallet theft — the jsonspack loader architecture has historically dropped browser-extension wallet stealers, clipboard hijackers, and ~/.aws/credentials / ~/.ssh/* exfiltrators consistent with DPRK financial-targeting priorities

What to do

  1. 1Remove every reference to chai-as-persisted from package.json / lockfiles / CI image layers — the live npm record still serves both 4.2.8 and 6.1.9 at the time of this advisory; no 0.0.1-security holder has been published yet
  2. 2Treat any host that ran npm install against a manifest pinning chai-as-persisted as fully compromised: rotate all credentials, browser session cookies, SSH keys, npm tokens, GitHub tokens, AWS / GCP / Azure CLI tokens, and crypto-wallet seed phrases from a separate clean device
  3. 3Block ipregionchecker.org (the C2 endpoint) at egress; hunt firewall and DNS logs for outbound HTTP/HTTPS to this domain since 2026-06-27
  4. 4Use the legitimate chai-as-promised package; verify the name letter-by-letter — chai-as-promised, not chai-as-persisted
  5. 5Scan internal Artifactory / Nexus / Verdaccio mirrors for cached tarballs of chai-as-persisted and purge them — public npm yank does not flush private caches
  6. 6Hunt for other chai-as-* packages with hello@jsonspack.com in package.json bugs.url (e.g. https://jsonspack.com/issues) — Panther previously confirmed chai-as-adapter, chai-beta, chai-str, chai-as-hooked, chai-as-redeployed, chai-as-encrypted and other siblings in this same campaign cluster

References

npm-2026-06-27-chai-as-persisted-jsonspack