⚡️ Run a static analysis of your module's dependencies.
Requirements
- Node.js version 22 or higher
Features
Scanner builds on JS-X-Ray (SAST) and Vulnera (CVE detection), and adds additional detections such as:
- Detects:
- Manifest confusion
- Dependency confusion
- Typosquatting of popular package names
- Install scripts (e.g.
install,preinstall,postinstall,preuninstall,postuninstall)
- Highlights packages by name, version(s), or maintainer
- Highlights infrastructure components such as ip, hostname, email, url
- Supports NPM and Yarn lockfiles
Getting Started
This package is available in the Node Package Repository and can be easily installed with npm or yarn.
$ npm i @nodesecure/scanner
# or
$ yarn add @nodesecure/scannerUsage example
import * as scanner from "@nodesecure/scanner"; import fs from "node:fs/promises"; // CONSTANTS const kPackagesToAnalyze = ["mocha", "cacache", "is-wsl"]; const payloads = await Promise.all( kPackagesToAnalyze.map((name) => scanner.from(name)) ); const promises = []; for (let i = 0; i < kPackagesToAnalyze.length; i++) { const data = JSON.stringify(payloads[i], null, 2); promises.push(fs.writeFile(`${kPackagesToAnalyze[i]}.json`, data)); } await Promise.allSettled(promises);
See types.ts for a complete TypeScript definition.
function workingDir( location: string, options?: Scanner.WorkingDirOptions, logger?: Scanner.Logger ): Promise<Scanner.Payload>; function from( packageName: string, options?: Scanner.FromOptions, logger?: Scanner.Logger ): Promise<Scanner.Payload>; function verify( packageName?: string ): Promise<tarball.ScannedPackageResult>;
WorkingDirOptions and FromOptions are described with the following TypeScript interfaces:
type WorkingDirOptions = Options & { /** * NPM runtime configuration (such as local .npmrc file) * It is optionally used to fetch registry authentication tokens */ npmRcConfig?: Config; }; type FromOptions = Omit<Options, "includeDevDeps">; interface Options { /** * Specifies the maximum depth to traverse for each root dependency. * A value of 2 would mean only traversing deps and their immediate deps. * * @default Infinity */ readonly maxDepth?: number; /** * Maximum concurrency to fetch and scan NPM tarballs * @default 8 */ readonly maxConcurrency?: number; /** * Includes development dependencies in the walk. * Note that enabling this option can significantly increase I/O and processing time. * * @default false */ includeDevDeps?: boolean; readonly registry?: string | URL; /** * Enables the use of Arborist for rapidly walking over the dependency tree. * When enabled, it triggers different methods based on the presence of `node_modules`: * - `loadActual()` if `node_modules` is available. * - `loadVirtual()` otherwise. * * When disabled, it will iterate on all dependencies by using pacote */ packageLock?: { /** * Fetches all manifests for additional metadata. * * @default false */ fetchManifest?: boolean; /** * Specifies the location of the manifest file for Arborist. * This is typically the path to the `package.json` file. */ location: string; }; highlight?: { contacts?: Contact[]; packages?: HighlightPackages; identifiers?: string[]; }; /** * Vulnerability strategy name (npm, snyk, node) * * @default NONE */ readonly vulnerabilityStrategy?: Vuln.Strategy.Kind; /** * Analyze root package. * * @default false for from() API * @default true for cwd() API */ readonly scanRootNode?: boolean; }
Additional APIs are available at:
Workspaces
Click on one of the links to access the documentation of the workspace:
| name | package and link |
|---|---|
| tarball | @nodesecure/tarball |
| tree-walker | @nodesecure/tree-walker |
| flags | @nodesecure/flags |
| mama | @nodesecure/mama |
| contact | @nodesecure/contact |
| conformance | @nodesecure/conformance |
| npm-types | @nodesecure/npm-types |
| i18n | @nodesecure/i18n |
| rc | @nodesecure/rc |
| utils | @nodesecure/utils |
| fs-walk | @nodesecure/fs-walk |
| github | @nodesecure/github |
| gitlab | @nodesecure/gitlab |
Contributors ✨
Thanks goes to these wonderful people (emoji key):
License
MIT
