An open API service indexing awesome lists of open source software.

https://github.com/nodesecure/js-x-ray

JavaScript & Node.js open-source SAST scanner. A static analyser for detecting most common malicious patterns πŸ”¬.
https://github.com/nodesecure/js-x-ray

ast ast-analysis javascript nodejs sast security security-audit security-tools supply-chain-security

Last synced: 4 days ago
JSON representation

JavaScript & Node.js open-source SAST scanner. A static analyser for detecting most common malicious patterns πŸ”¬.

Awesome Lists containing this project

README

          


@nodesecure/js-x-ray



npm version


license


ossf scorecard


slsa level3


github ci workflow

**JS-X-Ray** is a JavaScript & TypeScript [SAST](https://github.com/resources/articles/what-is-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](https://github.com/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)
- 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](https://docs.npmjs.com/getting-started/what-is-npm) or [yarn](https://yarnpkg.com).

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

## πŸ‘€ Usage example

Create a local `.js` file with the following content:
```js
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:
```js
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`.

> [!TIP]
> 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:

```ts
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](./workspaces/js-x-ray/docs/EntryFilesAnalyser.md) for more details.

## πŸ“š API

- [AstAnalyser](./workspaces/js-x-ray/docs/AstAnalyser.md)
- [EntryFilesAnalyser](./workspaces/js-x-ray/docs/EntryFilesAnalyser.md)
- [CollectableSet](./workspaces/js-x-ray/docs/CollectableSet.md)
- [SourceParser](./workspaces/js-x-ray/docs/SourceParser.md)
- [VariableTracer](./workspaces/js-x-ray/docs/VariableTracer.md)

## Warnings

```ts
type OptionalWarningName =
| "synchronous-io"
| "log-usage";

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

interface Warning {
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;
```

### Optional Warnings

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

```js
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"]
});
```

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.)

### Internationalization (i18n)

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

```js
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](./docs/suspicious-file.md) | No | Suspicious file containing more than ten encoded literals |
| [obfuscated-code](./docs/obfuscated-code.md) | **Yes** | High probability of code obfuscation detected |

#### Warning Severity

| Name | Experimental | Description |
| --- | :-: | --- |
| [unsafe-import](./docs/unsafe-import.md) | No | Unable to follow an import (`require`, `require.resolve`) statement |
| [unsafe-regex](./docs/unsafe-regex.md) | No | Unsafe regular expression that may be vulnerable to ReDoS attacks |
| [unsafe-stmt](./docs/unsafe-stmt.md) | No | Usage of dangerous statements like `eval()` or `Function("")` |
| [unsafe-command](./docs/unsafe-command.md) | **Yes** | Suspicious commands detected in `spawn()` or `exec()` |
| [short-identifiers](./docs/short-identifiers.md) | No | Average identifier length below 1.5 characters (possible obfuscation) |
| [suspicious-literal](./docs/suspicious-literal.md) | No | Suspicious literal values detected in source code |
| [weak-crypto](./docs/weak-crypto.md) | No | Usage of weak cryptographic algorithms (MD5, SHA1, etc.) |
| [shady-link](./docs/shady-link.md) | No | Suspicious or potentially malicious URLs detected |
| [synchronous-io](./docs/synchronous-io.md) ⚠️ | **Yes** | Synchronous I/O operations that may impact performance |
| [serialize-environment](./docs/serialize-environment.md) | No | Attempts to serialize `process.env` (potential data exfiltration) |
| [data-exfiltration](./docs/data-exfiltration.md) | No | Potential unauthorized transfer of sensitive data |
| [sql-injection](./docs/sql-injection.md) | No | Potential SQL injection vulnerability detected |
| [monkey-patch](./docs/monkey-patch.md) | No | Modification of built-in JavaScript prototype properties |

#### Information Severity

| Name | Experimental | Description |
| --- | :-: | --- |
| [parsing-error](./docs/parsing-error.md) | No | AST parser encountered an error while analyzing the code |
| [encoded-literal](./docs/encoded-literal.md) | No | Encoded literal detected (hexadecimal, Unicode, base64) |
| [log-usage](./docs/log-usage.md) ⚠️ | No | Usage of logging functions (console.log, logger methods, etc.) |

> [!NOTE]
> Warnings marked with ⚠️ are optional and must be explicitly enabled (see [Optional Warnings](#optional-warnings) section).

## Contributors guide

If you are a developer **looking to contribute** to the project, you must first read the [CONTRIBUTING](./CONTRIBUTING.md) guide.

Once you have finished your development, check that the tests (and linter) are still good by running the following script:

```bash
$ npm run check
```

> [!CAUTION]
> In case you introduce a new feature or fix a bug, make sure to include tests for it as well.

### Internal APIs

For contributors working on the JS-X-Ray internals, the following resources document low-level utilities and AST manipulation patterns:

- [ESTree utilities](./workspaces/js-x-ray/src/estree/README.md) - Low-level helpers to manipulate ESTree AST nodes
- [ESTree assignment and declaration patterns (french)](./workspaces/js-x-ray/docs/estree/patterns-french.md) - Reference guide for JavaScript assignment and declaration patterns in AST form

### Benchmarks

The performance of js-x-ray is measured and tracked using [mitata](https://github.com/evanwashere/mitata).

To run the benchmarks:
1. Navigate to `workspaces/js-x-ray`.
2. Run `npm run bench`.

The benchmark results are stored in workspaces/js-x-ray/benchmark/report.json. Do not edit this file manually; it is automatically updated on every pull request.

### Workspaces

Click on one of the links to access the documentation of the workspace:

| name | package and link |
| --- | --- |
| js-x-ray | [@nodesecure/js-x-ray](./workspaces/js-x-ray) |
| js-x-ray-ai | [@nodesecure/js-x-ray-ai](./workspaces/js-x-ray-ai) |

These packages are available in the Node package repository and can be easily installed with [npm](https://docs.npmjs.com/getting-started/what-is-npm) or [yarn](https://yarnpkg.com).
```bash
$ npm i @nodesecure/estree-ast-util
# or
$ yarn add @nodesecure/estree-ast-util
```

## Contributors ✨

[![All Contributors](https://img.shields.io/badge/all_contributors-22-orange.svg?style=flat-square)](#contributors-)

Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):



Gentilhomme
Gentilhomme

πŸ’» πŸ“– πŸ‘€ πŸ›‘οΈ πŸ›
Nicolas Hallaert
Nicolas Hallaert

πŸ“–
Antoine
Antoine

πŸ’»
Mathieu
Mathieu

πŸ’»
Vincent Dhennin
Vincent Dhennin

πŸ’» ⚠️
Tony Gorez
Tony Gorez

πŸ’» πŸ“– ⚠️
PierreD
PierreD

⚠️ πŸ’»


Franck Hallaert
Franck Hallaert

πŸ’»
Maji
Maji

πŸ’»
MichaΓ«l Zasso
MichaΓ«l Zasso

πŸ’» πŸ›
Kouadio Fabrice Nguessan
Kouadio Fabrice Nguessan

🚧 πŸ’»
Jean
Jean

⚠️ πŸ’» πŸ“–
tchapacan
tchapacan

πŸ’» ⚠️
mkarkkainen
mkarkkainen

πŸ’»


FredGuiou
FredGuiou

πŸ“– πŸ’»
Madina
Madina

πŸ’»
SairussDev
SairussDev

πŸ’»
Abdou-Raouf ATARMLA
Abdou-Raouf ATARMLA

πŸ’»
Clement Gombauld
Clement Gombauld

πŸ’» ⚠️
Ajāy
Ajāy

πŸ’»
Michael Mior
Michael Mior

πŸ“–


Hamed Mohamed
Hamed Mohamed

πŸ’»

## License
MIT