Research

96 fake chai plugins on npm that fetch and run remote code

Between May 7, 2026 and Oct 2, 2026, 96 npm packages posed as chai, the JavaScript assertion library, or as plugins for it. Behind the familiar API, most start a hidden Node process that downloads JavaScript and runs it.

Published LPM Firewall research

Summary

  • 96 packages and 160 versions. 60 of the names follow the chai-as-… pattern of the popular chai-as-promised.
  • 43 ship copied chai code, README files or metadata so they look and work like the real thing.
  • In 55, a detached child process fetches code and runs it with new Function, outside the test run.
  • 60 fetch from paste and hosting services such as jsonkeeper, jsonstorage, npoint, tiiny.site and Vercel apps.
  • Only 4 use an install script. The rest run when the package is imported or its exported helper is called.
  • LPM's own review confirms 36 as malicious, and 90 have an OpenSSF/OSV malicious-package advisory.

How the loader works

  1. Most of the packages export working assertions or copied library code, so a test that uses one still passes.
  2. On import, or the first time its exported middleware or helper is called, index.js spawns a detached Node process running a helper such as lib/caller.js or lib/initializeCaller.js, with its output discarded.
  3. The helper decodes a URL hidden with Base64 or a similar encoding and requests it, often from a paste or JSON hosting service.
  4. It runs the response, or a field from it such as cookie or token, with new Function("require", …), giving the downloaded code full access to Node.

The detached process outlives the test run, and the payload can change on the server at any time. In 9 packages the helper also sends the full process.env, which in CI usually holds cloud, registry and deployment tokens. See all npm packages with remote code execution.

Who they target

Test helpers are installed by developers and run in CI, where credentials are close at hand. Several names and payloads point at web3 developers: 10 packages mention wallets, Solidity or Ethereum, and names such as chai-web3-testkit, chai-solidity-testkit and chai-as-viem fit smart-contract test setups.

Indicators of compromise

Payload hosts

  • https://ipcheck-hashed.vercel.app/api/auth/<id>
  • https://ipcheckr-hashed.vercel.app/api/auth/<id>
  • http://check-server-state.vercel.app/server/v2
  • http://server-genimi-check.vercel.app/defy/v3
  • https://statecheck.ddns.net/api/scanner.js
  • http://coolblast.zapto.org:8888/api/x-handler
  • https://www.ipregionchecker.org/api/ip-check-encrypted/<id>
  • https://testlog.edgeone.cool/data.json
  • https://1uznbx.s.gy/7xdQmt

Abused paste and hosting services (block the paths, not the services)

  • https://jsonkeeper.com/b/<id> (PC5CK, XRGF3, 4NAKK, 5IZTJ, U2BTS, CS0FU, O3JR0, EXSIF, HIOEN, AAON3, HIECD)
  • https://api.jsonstorage.net/v1/json/2ef8c758-a96f-459e-b036-b3b90379a165/<id>
  • https://api.npoint.io/c2e881b8bc0fe2121454
  • https://api.npoint.io/c26313f0733957a7d787
  • https://<name>.tiiny.site/index.json (amethyst-lorrin-26, tomato-brunhilda-40, tomato-erminie-2, gray-dyane-31, aqua-margit-84)
  • https://purple-kelila-79.tiiny.site/data.json

Loader file names inside the packages

  • lib/caller.js
  • lib/initializeCaller.js
  • lib/initstate.js
  • lib/syncResolve.js
  • lib/config.js

What to do

  • Search package.json files and lockfiles for the names below. The real packages are chai and chai-as-promised, published by the chai maintainers.
  • If one of them ran in a test or CI job, treat that machine as compromised and rotate every credential its environment held.
  • Look for detached node lib/caller.js or similar processes left running after tests.
  • Block the hosts and paths above at network egress.

Affected packages

96 packages. Each name links to its LPM Firewall report and is marked LPM confirmed or advisory.

How we identified the packages

The list covers every npm package LPM Firewall blocks whose name starts with chai-, plus express-chai, as of Oct 23, 2026. The packages share a disguise and a loader pattern, but not necessarily one publisher. The counts of each behavior come from LPM's reviews and the advisory text for each package, so they are lower bounds.

Read how LPM Firewall reports are produced, or browse more research.