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 π¬.
- Host: GitHub
- URL: https://github.com/nodesecure/js-x-ray
- Owner: NodeSecure
- License: mit
- Created: 2020-03-26T21:15:45.000Z (almost 6 years ago)
- Default Branch: master
- Last Pushed: 2025-05-05T10:19:10.000Z (9 months ago)
- Last Synced: 2025-05-09T00:34:42.252Z (9 months ago)
- Topics: ast, ast-analysis, javascript, nodejs, sast, security, security-audit, security-tools, supply-chain-security
- Language: JavaScript
- Homepage:
- Size: 1.19 MB
- Stars: 242
- Watchers: 5
- Forks: 24
- Open Issues: 6
-
Metadata Files:
- Readme: README.md
- Contributing: CONTRIBUTING.md
- License: LICENSE
- Security: SECURITY.md
Awesome Lists containing this project
README
**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 β¨
[](#contributors-)
Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):

Gentilhomme
π» π π π‘οΈ π

Nicolas Hallaert
π

Antoine
π»

Mathieu
π»

Vincent Dhennin
π» β οΈ

Tony Gorez
π» π β οΈ

PierreD
β οΈ π»

Franck Hallaert
π»

Maji
π»

MichaΓ«l Zasso
π» π

Kouadio Fabrice Nguessan
π§ π»

Jean
β οΈ π» π

tchapacan
π» β οΈ

mkarkkainen
π»

FredGuiou
π π»

Madina
π»

SairussDev
π»

Abdou-Raouf ATARMLA
π»

Clement Gombauld
π» β οΈ

AjΔy
π»

Michael Mior
π

Hamed Mohamed
π»
## License
MIT