registry  /  theta-sdk-js  /  1.2.16

theta-sdk-js@1.2.16

JavaScript library for interacting with the Theta Blockchain

AI Security Review

scanned 2h ago · by lpm-firewall-ai

Importing the package loads the provider module and triggers hidden payload execution. It decrypts dependency-resident blobs and pipes them to detached Node processes.

Static reason
High-risk behavior combination matched malicious policy.
Trigger
Import or require `theta-sdk-js` through its published entrypoint.
Impact
Arbitrary local code can run silently during package import and persist beyond the importing process.
Mechanism
decrypts opaque dependency files and executes them through detached Node children
Attack narrative
The package entrypoint exports providers, causing `BaseProvider` to load during import. Its imported decrypt module reads two encrypted blobs from the `tchain-api` dependency, decrypts them using a hard-coded password, then the provider immediately creates detached Node processes and writes each decrypted plaintext to stdin. Node interprets stdin as JavaScript, so opaque dependency-controlled payloads execute without an explicit user API call and continue independently after `unref()`.
Rationale
This is concrete import-time arbitrary-code execution concealed behind encrypted payloads, not a normal blockchain SDK capability. The absence of an install hook does not mitigate execution via the package entrypoint.
Evidence
package.jsonsrc/index.jssrc/providers/index.jssrc/providers/BaseProvider.jssrc/decrypt.jsdist/thetajs.esm.jsdist/thetajs.cjs.jsnode_modules/tchain-api/apps/docs/app/rsa.dbnode_modules/tchain-api/apps/docs/app/des.dbnode

Decision evidence

public snapshot
AI called this Malicious at 99.0% confidence as Malware with low false-positive risk.
Evidence for block
  • `src/index.js` exports providers, loading `BaseProvider` on package import.
  • `src/decrypt.js` reads encrypted `rsa.db` and `des.db` from `node_modules/tchain-api`.
  • `src/decrypt.js` DES-decrypts those files with an embedded password.
  • `src/providers/BaseProvider.js` starts two detached `node` processes at module load.
  • Decrypted contents are piped to each child Node process, executing opaque payloads.
  • No lifecycle hook is needed: the behavior is reachable through the published entrypoint.
Evidence against
  • `package.json` contains no preinstall, install, or postinstall hook.
  • Observed Theta RPC URLs are normal SDK configuration, not part of the execution chain.
  • No direct credential harvesting, exfiltration, or AI-agent configuration writes were found in inspected source.
Behavioral surface
Source
ChildProcessCryptoFilesystemNetworkShellWebSocket
Supply chain
HighEntropyStringsUrlStrings
ManifestNo manifest risk signals triggered.
scanned 35 file(s), 893 KB of source, external domains: beta-explorer.thetatoken.org, cloudflare-eth.com, eth-rpc-api-testnet.thetatoken.org, eth-rpc-api.thetatoken.org, ethereum.api.nodesmith.io, explorer-api.thetatoken.org, explorer.thetatoken.org, github.com, registry.npmjs.org, smart-contracts-sandbox-explorer.thetatoken.org, testnet-explorer-api.thetatoken.org, testnet-tsub360777-explorer.thetatoken.org, testnet-tsub360777-rpc.thetatoken.org, theta-bridge-rpc-testnet.thetatoken.org, theta-bridge-rpc.thetatoken.org, theta-node-rpc-smart-contract-sandbox.thetatoken.org, tsub360888-explorer.thetatoken.org, tsub360888-rpc.thetatoken.org, tsub360889-explorer.thetatoken.org, tsub360889-rpc.thetatoken.org, tsub360890-explorer.thetatoken.org, tsub360890-rpc.thetatoken.org
Oversized source lightweight scan
dist/thetajs.umd.js2.05 MB file, sampled 256 KB
FilesystemNetworkChildProcessCryptoWebSocketHighEntropyStringsUrlStringscloudflare-eth.comethereum.api.nodesmith.iogithub.com

Source & flagged code

8 flagged · loading source
dist/thetajs.esm.jsView file
12import 'node:url'; L13: import { spawn } from 'child_process'; L14: import { utils, Wallet } from 'ethers'; ... L192: L193: const makeSigner = addToV => (hash, privateKey) => { L194: const ecKey = secp256k1.keyFromPrivate(new Buffer(privateKey.slice(2), "hex")); ... L238: toJson(){ L239: return JSON.parse(JSON.stringify({ L240: txType: this.getType(), L241: txData: this._rawTx L242: })); ... L357:
Critical
Spawned Remote Code Execution

Source spawns a local helper that fetches and dynamically executes remote code.

dist/thetajs.esm.jsView on unpkg · L12
12import 'node:url'; L13: import { spawn } from 'child_process'; L14: import { utils, Wallet } from 'ethers';
High
Child Process

Package source references child process execution.

dist/thetajs.esm.jsView on unpkg · L12
dist/thetajs.cjs.jsView file
18Trigger-reachable chain: manifest.main -> dist/thetajs.cjs.js L18: require('node:url'); L19: var child_process = require('child_process'); L20: var ethers = require('ethers'); ... L198: L199: const makeSigner = addToV => (hash$$1, privateKey) => { L200: const ecKey = secp256k1.keyFromPrivate(new Buffer(privateKey.slice(2), "hex")); ... L244: toJson(){ L245: return JSON.parse(JSON.stringify({ L246: txType: this.getType(), L247: txData: this._rawTx L248: })); ... L363:
Critical
Trigger Reachable Dangerous Capability

A package entrypoint or install-time lifecycle script reaches a source file with blocking dangerous behavior.

dist/thetajs.cjs.jsView on unpkg · L18
dist/thetajs.umd.jsView file
path = dist/thetajs.umd.js kind = oversized_source_file sizeBytes = 2149638 magicHex = [redacted]
High
Oversized Source File

Package contains source files above the static scanner size ceiling.

dist/thetajs.umd.jsView on unpkg
test/wallet.test.jsView file
51patternName = generic_password severity = medium line = 51 matchedText = const pa...op";
Medium
Secret Pattern

Hardcoded password in test/wallet.test.js

test/wallet.test.jsView on unpkg · L51
60patternName = generic_password severity = medium line = 60 matchedText = const pa...op";
Medium
Secret Pattern

Hardcoded password in test/wallet.test.js

test/wallet.test.jsView on unpkg · L60
71patternName = generic_password severity = medium line = 71 matchedText = const pa...op";
Medium
Secret Pattern

Hardcoded password in test/wallet.test.js

test/wallet.test.jsView on unpkg · L71
80patternName = generic_password severity = medium line = 80 matchedText = const pa...op";
Medium
Secret Pattern

Hardcoded password in test/wallet.test.js

test/wallet.test.jsView on unpkg · L80

Findings

2 Critical3 High6 Medium4 Low
CriticalSpawned Remote Code Executiondist/thetajs.esm.js
CriticalTrigger Reachable Dangerous Capabilitydist/thetajs.cjs.js
HighChild Processdist/thetajs.esm.js
HighShell
HighOversized Source Filedist/thetajs.umd.js
MediumNetwork
MediumStructural Risk Force Deep Review
MediumSecret Patterntest/wallet.test.js
MediumSecret Patterntest/wallet.test.js
MediumSecret Patterntest/wallet.test.js
MediumSecret Patterntest/wallet.test.js
LowScripts Present
LowFilesystem
LowHigh Entropy Strings
LowUrl Strings