npm.io
16.1.0 • Published 2 weeks ago

@nodesecure/js-x-ray

Licence
MIT
Version
16.1.0
Deps
7
Size
548 kB
Vulns
0
Weekly
0
Stars
288

@nodesecure/js-x-ray

JS-X-Ray is a JavaScript & TypeScript SAST for identifying malicious patterns, security vulnerabilities, and code anomalies. Think of it as ESLint, but dedicated to security analysis. Originally created for NodeSecure CLI, JS-X-Ray has become an independent and serious option for supply chain protection.

How It Works

JS-X-Ray parses JS or TS code into an Abstract Syntax Tree (AST) with no extensive usage of RegEx or Semgrep rules. This enables variable tracing, dynamic import resolution, and detection of sophisticated obfuscation that pattern-matching tools miss. The tradeoff is that JS-X-Ray is purely dedicated to the JavaScript/TypeScript ecosystem.

Features

  • Retrieve required dependencies and files for Node.js
    • Track require(), import, and dynamic imports with full tracing capabilities
    • Detect untraceable and malicious import patterns
  • Scan entire projects with multi-file analysis capabilities
  • Extract infrastructure components (URLs, IPs, hostnames, emails)
  • Detect malicious code patterns
    • Obfuscated code with tool identification (freejsobfuscator, jsfuck, jjencode, obfuscator.io, morse, Trojan Source)
    • Data exfiltration and unauthorized system information collection
    • Suspicious files with excessive encoded literals
  • Identify vulnerable code patterns
    • Unsafe statements (eval(), Function() constructor)
    • ReDoS vulnerabilities in regular expressions
    • SQL injection vulnerabilities
    • Unsafe shell commands in spawn() or exec() calls
    • process.env serialization attempts
  • Flag weak cryptographic usage
    • Deprecated algorithms (MD5, SHA1, MD4, MD2, RIPEMD160)
    • Weak scrypt parameters (insufficient cost, short or hardcoded salt)
    • Weak bcrypt parameters (low work factor, hardcoded salt)
  • Detect code quality issues
    • Monkey-patching of built-in prototypes
    • Encoded literals (hex, Unicode, base64)
    • Suspicious URLs and links
    • Short identifier lengths (obfuscation indicators)
    • Synchronous I/O and logging usage (optional)
  • Configurable sensitivity modes (conservative/aggressive) and extensible probe system
  • Support both JavaScript and TypeScript

Getting Started

This package is available in the Node package repository and can be easily installed with npm or yarn.

$ npm i @nodesecure/js-x-ray
# or
$ yarn add @nodesecure/js-x-ray

Usage example

Create a local .js file with the following content:

try  {
    require("http");
}
catch (err) {
    // do nothing
}
const lib = "crypto";
require(lib);
require("util");
require(Buffer.from("6673", "hex").toString());

Then use js-x-ray to run an analysis of the JavaScript code:

import { AstAnalyser } from "@nodesecure/js-x-ray";
import { readFileSync } from "node:fs";

const scanner = new AstAnalyser();

const { warnings, dependencies } = await scanner.analyseFile(
  "./file.js"
);

console.log(dependencies);
console.dir(warnings, { depth: null });

The analysis will return: http (in try), crypto, util and fs.

There are also a lot of suspicious code examples in the ./workspaces/js-x-ray/examples directory. Feel free to try the tool on these files.

Scanning a complete project

By itself, JS-X-Ray does not provide utilities to walk and scan a complete project. However, NodeSecure has packages to achieve that:

import { ManifestManager } from "@nodesecure/mama";
import { NpmTarball } from "@nodesecure/tarball";

const mama = await ManifestManager.fromPackageJSON(
  "./path/to/package.json"
);
const extractor = new NpmTarball(mama);

const {
  composition, // Project composition (files, dependencies, extensions)
  conformance, // License conformance (SPDX)
  code         // JS-X-Ray analysis results
} = await extractor.scanFiles();

console.log(code);

The NpmTarball class uses JS-X-Ray under the hood, and ManifestManager locates entry (input) files for analysis.

Alternatively, you can use EntryFilesAnalyser directly for multi-file analysis. See the EntryFilesAnalyser API documentation for more details.

API

Warnings

type OptionalWarningName =
  | "synchronous-io"
  | "log-usage"
  | "crypto.weak-scrypt"
  | "crypto.unsafe-prehash"
  | "crypto.weak-bcrypt"
  | "crypto.password-shucking"
  | "crypto.weak-argon2";

type WarningName =
  | "parsing-error"
  | "encoded-literal"
  | "unsafe-regex"
  | "unsafe-stmt"
  | "short-identifiers"
  | "suspicious-literal"
  | "suspicious-file"
  | "obfuscated-code"
  | "crypto.weak-algorithm"
  | "shady-link"
  | "unsafe-command"
  | "unsafe-import"
  | "serialize-environment"
  | "data-exfiltration"
  | "sql-injection"
  | "monkey-patch"
  | "prototype-pollution"
  | "unsafe-vm-context"
  | OptionalWarningName;

interface Warning<T = WarningName> {
  kind: T | (string & {});
  file?: string;
  value: string | null;
  source: string;
  location: null | SourceArrayLocation | SourceArrayLocation[];
  i18n: string;
  severity: "Information" | "Warning" | "Critical";
  experimental?: boolean;
}

declare const warnings: Record<WarningName, {
  i18n: string;
  severity: "Information" | "Warning" | "Critical";
  experimental: boolean;
}>;
Optional Warnings

Some warnings are not included by default and must be explicitly requested through the AstAnalyser API.

import { AstAnalyser } from "@nodesecure/js-x-ray";

// Enable all optional warnings
const scanner = new AstAnalyser({
  optionalWarnings: true
});

// Or enable specific optional warnings
const scannerSpecific = new AstAnalyser({
  optionalWarnings: ["synchronous-io", "log-usage", "crypto.weak-scrypt"]
});

// Enable all crypto warnings at once using a glob pattern
const scannerCrypto = new AstAnalyser({
  optionalWarnings: ["crypto.*"]
});

The following warnings are optional:

  • synchronous-io - Detects synchronous I/O operations that could impact performance
  • log-usage - Tracks usage of logging functions (console.log, logger.info, etc.)
  • crypto.weak-scrypt - Detects weak scrypt parameters (low cost, short or hardcoded salt)
  • crypto.unsafe-prehash - Detects password pre-hashing fed into bcrypt without a safe (base64/hex) digest encoding
  • crypto.weak-bcrypt - Detects weak bcrypt parameters (low work factor, hardcoded salt)
  • crypto.password-shucking - Detects password pre-hashing with a plain hash function fed into bcrypt
  • crypto.weak-argon2 - Detects weak Argon2 parameters (argon2d variant, low memory/passes, short or hardcoded nonce)
Internationalization (i18n)

Warnings support internationalization through the @nodesecure/i18n package. Each warning has an i18n key that can be used to retrieve localized descriptions.

import * as jsxray from "@nodesecure/js-x-ray";
import * as i18n from "@nodesecure/i18n";

await i18n.extendFromSystemPath(jsxray.i18nLocation());

const message = i18n.getTokenSync(
  jsxray.warnings["parsing-error"].i18n
);
console.log(message);
Warning Catalog

Click on the warning name for detailed documentation and examples.

Critical Severity
Name Experimental Description
suspicious-file No Suspicious file containing more than ten encoded literals
obfuscated-code Yes High probability of code obfuscation detected
Warning Severity
Name Experimental Description
unsafe-import No Unable to follow an import (require, require.resolve) statement
unsafe-regex No Unsafe regular expression that may be vulnerable to ReDoS attacks
unsafe-stmt No Usage of dangerous statements like eval() or Function("")
unsafe-command Yes Suspicious commands detected in spawn() or exec()
short-identifiers No Average identifier length below 1.5 characters (possible obfuscation)
suspicious-literal No Suspicious literal values detected in source code
crypto.weak-algorithm No Usage of weak cryptographic algorithms (MD5, SHA1, etc.)
shady-link No Suspicious or potentially malicious URLs detected
synchronous-io Yes Synchronous I/O operations that may impact performance
serialize-environment No Attempts to serialize process.env (potential data exfiltration)
data-exfiltration No Potential unauthorized transfer of sensitive data
sql-injection No Potential SQL injection vulnerability detected
monkey-patch No Modification of built-in JavaScript prototype properties
prototype-pollution No Detected use of __proto__ to pollute object prototypes
crypto.weak-scrypt Yes Usage of weak scrypt parameters (low cost, short or hardcoded salt)
crypto.unsafe-prehash Yes Password pre-hashed and fed into bcrypt without a safe digest encoding
crypto.weak-bcrypt Yes Usage of weak bcrypt parameters (low work factor or hardcoded salt)
crypto.password-shucking Yes Password pre-hashed with a plain hash function
crypto.weak-argon2 Yes Usage of weak Argon2 parameters (argon2d variant, low memory/passes, short or hardcoded nonce)
unsafe-vm-context No Usage of dangerous vm.runInNewContext and (vm.Script(code,options)).runInContext
Information Severity
Name Experimental Description
parsing-error No AST parser encountered an error while analyzing the code
encoded-literal No Encoded literal detected (hexadecimal, Unicode, base64)
log-usage No Usage of logging functions (console.log, logger methods, etc.)

Warnings marked with are optional and must be explicitly enabled (see Optional Warnings section).

License

MIT

Keywords