@nodesecure/scanner 2.0.0 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +1 -1
- package/README.md +95 -94
- package/index.js +4 -4
- package/package.json +19 -36
- package/src/{dependency.class.js → class/dependency.class.js} +22 -21
- package/src/{logger.class.js → class/logger.class.js} +0 -0
- package/src/depWalker.js +298 -347
- package/src/manifest.js +57 -0
- package/src/npmRegistry.js +68 -0
- package/src/tarball.js +85 -188
- package/src/utils/addMissingVersionFlags.js +24 -0
- package/src/utils/analyzeDependencies.js +40 -0
- package/src/utils/booleanToFlags.js +12 -0
- package/src/utils/filterDependencyKind.js +44 -0
- package/src/utils/getPackageName.js +18 -2
- package/src/utils/getTarballComposition.js +8 -10
- package/src/utils/index.js +16 -14
- package/src/utils/isGitDependency.js +20 -0
- package/src/utils/isSensitiveFile.js +6 -0
- package/src/utils/mergeDependencies.js +26 -23
- package/src/utils/semver.js +3 -3
- package/types/logger.d.ts +2 -0
- package/types/scanner.d.ts +128 -32
package/src/utils/index.js
CHANGED
|
@@ -1,14 +1,16 @@
|
|
|
1
|
-
export * from "./getTarballComposition.js";
|
|
2
|
-
export * from "./isSensitiveFile.js";
|
|
3
|
-
export * from "./
|
|
4
|
-
export * from "./
|
|
5
|
-
export * from "./
|
|
6
|
-
export * from "./
|
|
7
|
-
export * from "./
|
|
8
|
-
|
|
9
|
-
export
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
1
|
+
export * from "./getTarballComposition.js";
|
|
2
|
+
export * from "./isSensitiveFile.js";
|
|
3
|
+
export * from "./isGitDependency.js";
|
|
4
|
+
export * from "./getPackageName.js";
|
|
5
|
+
export * from "./mergeDependencies.js";
|
|
6
|
+
export * from "./semver.js";
|
|
7
|
+
export * from "./dirname.js";
|
|
8
|
+
export * from "./warnings.js";
|
|
9
|
+
export * from "./filterDependencyKind.js";
|
|
10
|
+
export * from "./analyzeDependencies.js";
|
|
11
|
+
export * from "./booleanToFlags.js";
|
|
12
|
+
export * from "./addMissingVersionFlags.js";
|
|
13
|
+
|
|
14
|
+
export const NPM_TOKEN = typeof process.env.NODE_SECURE_TOKEN === "string" ?
|
|
15
|
+
{ token: process.env.NODE_SECURE_TOKEN } :
|
|
16
|
+
{};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
const kGitVersionVariants = ["git:", "git+", "github:"];
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @example isGitDependency("github:NodeSecure/scanner") // => true
|
|
5
|
+
* @example isGitDependency("git+ssh://git@github.com:npm/cli#semver:^5.0") // => true
|
|
6
|
+
* @example isGitDependency(">=1.0.2 <2.1.2") // => false
|
|
7
|
+
* @example isGitDependency("http://asdf.com/asdf.tar.gz") // => false
|
|
8
|
+
* @param {string} version
|
|
9
|
+
* @returns {boolean}
|
|
10
|
+
*/
|
|
11
|
+
export function isGitDependency(version) {
|
|
12
|
+
for (const variant of kGitVersionVariants) {
|
|
13
|
+
if (version.startsWith(variant)) {
|
|
14
|
+
return true;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
return false;
|
|
19
|
+
}
|
|
20
|
+
|
|
@@ -5,6 +5,12 @@ import path from "path";
|
|
|
5
5
|
const kSensitiveFileName = new Set([".npmrc", ".env"]);
|
|
6
6
|
const kSensitiveFileExtension = new Set([".key", ".pem"]);
|
|
7
7
|
|
|
8
|
+
/**
|
|
9
|
+
* @see https://github.com/jandre/safe-commit-hook/blob/master/git-deny-patterns.json
|
|
10
|
+
*
|
|
11
|
+
* @param {!string} fileName
|
|
12
|
+
* @returns {boolean}
|
|
13
|
+
*/
|
|
8
14
|
export function isSensitiveFile(fileName) {
|
|
9
15
|
return kSensitiveFileName.has(path.basename(fileName)) ||
|
|
10
16
|
kSensitiveFileExtension.has(path.extname(fileName));
|
|
@@ -1,23 +1,26 @@
|
|
|
1
|
-
export function mergeDependencies(manifest, types = ["dependencies"]) {
|
|
2
|
-
const dependencies = new Map();
|
|
3
|
-
const customResolvers = new Map();
|
|
4
|
-
|
|
5
|
-
for (const fieldName of types) {
|
|
6
|
-
if (!Reflect.has(manifest, fieldName)) {
|
|
7
|
-
continue;
|
|
8
|
-
}
|
|
9
|
-
const dep = manifest[fieldName];
|
|
10
|
-
|
|
11
|
-
for (const [name, version] of Object.entries(dep)) {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
}
|
|
1
|
+
export function mergeDependencies(manifest, types = ["dependencies"]) {
|
|
2
|
+
const dependencies = new Map();
|
|
3
|
+
const customResolvers = new Map();
|
|
4
|
+
|
|
5
|
+
for (const fieldName of types) {
|
|
6
|
+
if (!Reflect.has(manifest, fieldName)) {
|
|
7
|
+
continue;
|
|
8
|
+
}
|
|
9
|
+
const dep = manifest[fieldName];
|
|
10
|
+
|
|
11
|
+
for (const [name, version] of Object.entries(dep)) {
|
|
12
|
+
/**
|
|
13
|
+
* Version can be file:, github:, git:, git+, ./...
|
|
14
|
+
* @see https://docs.npmjs.com/cli/v7/configuring-npm/package-json#dependencies
|
|
15
|
+
*/
|
|
16
|
+
if (/^([a-zA-Z]+:|git\+|\.\\)/.test(version)) {
|
|
17
|
+
customResolvers.set(name, version);
|
|
18
|
+
continue;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
dependencies.set(name, version);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return { dependencies, customResolvers };
|
|
26
|
+
}
|
package/src/utils/semver.js
CHANGED
|
@@ -4,7 +4,7 @@ import semver from "semver";
|
|
|
4
4
|
import { getLocalRegistryURL } from "@nodesecure/npm-registry-sdk";
|
|
5
5
|
|
|
6
6
|
// Import Internal Dependencies
|
|
7
|
-
import {
|
|
7
|
+
import { NPM_TOKEN } from "./index.js";
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
10
|
* @param {!string} version semver range
|
|
@@ -31,11 +31,11 @@ export function cleanRange(version) {
|
|
|
31
31
|
export async function getExpectedSemVer(depName, range) {
|
|
32
32
|
try {
|
|
33
33
|
const { versions, "dist-tags": { latest } } = await pacote.packument(depName, {
|
|
34
|
-
...
|
|
34
|
+
...NPM_TOKEN, registry: getLocalRegistryURL()
|
|
35
35
|
});
|
|
36
36
|
const currVersion = semver.maxSatisfying(Object.keys(versions), range);
|
|
37
37
|
|
|
38
|
-
return
|
|
38
|
+
return currVersion === null ? [latest, true] : [currVersion, semver.eq(latest, currVersion)];
|
|
39
39
|
}
|
|
40
40
|
catch (err) {
|
|
41
41
|
return [cleanRange(range), true];
|
package/types/logger.d.ts
CHANGED
package/types/scanner.d.ts
CHANGED
|
@@ -1,64 +1,133 @@
|
|
|
1
|
-
|
|
1
|
+
// Import NodeSecure Dependencies
|
|
2
|
+
import * as JSXRay from "@nodesecure/js-x-ray";
|
|
2
3
|
import { license as License } from "@nodesecure/ntlp";
|
|
3
|
-
import
|
|
4
|
+
import * as Vuln from "@nodesecure/vuln";
|
|
4
5
|
import { Flags } from "@nodesecure/flags";
|
|
6
|
+
|
|
7
|
+
// Import Third-party Dependencies
|
|
5
8
|
import { Maintainer } from "@npm/types";
|
|
6
9
|
|
|
7
10
|
export = Scanner;
|
|
8
11
|
|
|
9
12
|
declare namespace Scanner {
|
|
10
13
|
export interface Publisher {
|
|
14
|
+
/**
|
|
15
|
+
* Publisher npm user name.
|
|
16
|
+
*/
|
|
11
17
|
name: string;
|
|
18
|
+
/**
|
|
19
|
+
* Publisher npm user email.
|
|
20
|
+
*/
|
|
21
|
+
email: string;
|
|
22
|
+
/**
|
|
23
|
+
* First version published.
|
|
24
|
+
*/
|
|
12
25
|
version: string;
|
|
26
|
+
/**
|
|
27
|
+
* Date of the first publication
|
|
28
|
+
* @example 2021-08-10T20:45:08.342Z
|
|
29
|
+
*/
|
|
13
30
|
at: string;
|
|
14
31
|
}
|
|
15
32
|
|
|
16
|
-
export interface
|
|
33
|
+
export interface DependencyVersion {
|
|
34
|
+
/** Id of the package (useful for usedBy relation) */
|
|
35
|
+
id: number;
|
|
36
|
+
/** By whom (id) is used the package */
|
|
37
|
+
usedBy: Record<string, string>;
|
|
38
|
+
/** Size on disk of the extracted tarball (in bytes) */
|
|
39
|
+
size: number;
|
|
40
|
+
/** Package description */
|
|
41
|
+
description: string;
|
|
42
|
+
/** Author of the package. This information is not trustable and can be empty. */
|
|
43
|
+
author: Maintainer;
|
|
44
|
+
/**
|
|
45
|
+
* JS-X-Ray warnings
|
|
46
|
+
*
|
|
47
|
+
* @see https://github.com/NodeSecure/js-x-ray/blob/master/WARNINGS.md
|
|
48
|
+
*/
|
|
49
|
+
warnings: JSXRay.Warning<JSXRay.BaseWarning>[];
|
|
50
|
+
/** Tarball composition (files and dependencies) */
|
|
51
|
+
composition: {
|
|
52
|
+
/** Files extensions (.js, .md, .exe etc..) */
|
|
53
|
+
extensions: string[];
|
|
54
|
+
files: string[];
|
|
55
|
+
/** Minified files (foo.min.js etc..) */
|
|
56
|
+
minified: string[];
|
|
57
|
+
required_files: string[];
|
|
58
|
+
required_thirdparty: string[];
|
|
59
|
+
required_nodejs: string[];
|
|
60
|
+
unused: string[];
|
|
61
|
+
missing: string[];
|
|
62
|
+
};
|
|
63
|
+
/**
|
|
64
|
+
* Package licenses with SPDX expression.
|
|
65
|
+
*
|
|
66
|
+
* @see https://github.com/NodeSecure/licenses-conformance
|
|
67
|
+
* @see https://github.com/NodeSecure/npm-tarball-license-parser
|
|
68
|
+
*/
|
|
69
|
+
license: License[];
|
|
70
|
+
/**
|
|
71
|
+
* Flags (Array of string)
|
|
72
|
+
*
|
|
73
|
+
* @see https://github.com/NodeSecure/flags/blob/main/FLAGS.md
|
|
74
|
+
*/
|
|
75
|
+
flags: Flags[];
|
|
76
|
+
/**
|
|
77
|
+
* If the dependency is a GIT repository
|
|
78
|
+
*/
|
|
79
|
+
gitUrl: null | string;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export interface Dependency {
|
|
83
|
+
/** NPM Registry metadata */
|
|
17
84
|
metadata: {
|
|
85
|
+
/** Count of dependencies */
|
|
18
86
|
dependencyCount: number;
|
|
87
|
+
/** Number of releases published on npm */
|
|
19
88
|
publishedCount: number;
|
|
20
89
|
lastUpdateAt: number;
|
|
90
|
+
/** Last version SemVer */
|
|
21
91
|
lastVersion: number;
|
|
22
92
|
hasChangedAuthor: boolean;
|
|
23
93
|
hasManyPublishers: boolean;
|
|
24
94
|
hasReceivedUpdateInOneYear: boolean;
|
|
95
|
+
/** Author of the package. This information is not trustable and can be empty. */
|
|
25
96
|
author: Maintainer;
|
|
97
|
+
/** Package home page */
|
|
26
98
|
homepage: string | null;
|
|
27
|
-
|
|
99
|
+
/**
|
|
100
|
+
* List of maintainers (list of people in the organization related to the package)
|
|
101
|
+
*/
|
|
102
|
+
maintainers: { name: string, email: string }[];
|
|
103
|
+
/**
|
|
104
|
+
* List of people who published this package
|
|
105
|
+
*/
|
|
28
106
|
publishers: Publisher[];
|
|
29
107
|
}
|
|
30
|
-
versions
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
warnings: Warning<BaseWarning>[];
|
|
39
|
-
composition: {
|
|
40
|
-
extensions: string[];
|
|
41
|
-
files: string[];
|
|
42
|
-
minified: string[];
|
|
43
|
-
required_files: string[];
|
|
44
|
-
required_thirdparty: string[];
|
|
45
|
-
required_nodejs: string[];
|
|
46
|
-
unused: string[];
|
|
47
|
-
missing: string[];
|
|
48
|
-
};
|
|
49
|
-
license: string | License[];
|
|
50
|
-
flags: Flags;
|
|
51
|
-
gitUrl: null | string;
|
|
52
|
-
};
|
|
108
|
+
/** List of versions of this package available in the dependency tree (In the payload) */
|
|
109
|
+
versions: Record<string, DependencyVersion>;
|
|
110
|
+
/**
|
|
111
|
+
* Vulnerabilities fetched dependending on the selected vulnerabilityStrategy
|
|
112
|
+
*
|
|
113
|
+
* @see https://github.com/NodeSecure/vuln
|
|
114
|
+
*/
|
|
115
|
+
vulnerabilities: Vuln.Strategy.StandardVulnerability[];
|
|
53
116
|
}
|
|
54
117
|
|
|
55
118
|
export interface Payload {
|
|
119
|
+
/** Payload unique id */
|
|
56
120
|
id: string;
|
|
121
|
+
/** Name of the analyzed package */
|
|
57
122
|
rootDependencyName: string;
|
|
123
|
+
/** Global warnings list */
|
|
58
124
|
warnings: [];
|
|
59
|
-
dependencies
|
|
125
|
+
/** All the dependencies of the package (flattened) */
|
|
126
|
+
dependencies: Record<string, Dependency>;
|
|
127
|
+
/** Version of the scanner used to generate the result */
|
|
60
128
|
version: string;
|
|
61
|
-
|
|
129
|
+
/** Vulnerability strategy name (npm, snyk, node) */
|
|
130
|
+
vulnerabilityStrategy: Vuln.Strategy.Kind;
|
|
62
131
|
}
|
|
63
132
|
|
|
64
133
|
export interface VerifyPayload {
|
|
@@ -71,16 +140,43 @@ declare namespace Scanner {
|
|
|
71
140
|
uniqueLicenseIds: string[];
|
|
72
141
|
licenses: License[];
|
|
73
142
|
ast: {
|
|
74
|
-
dependencies: Record<string, Dependency>;
|
|
75
|
-
warnings: Warning<BaseWarning>[];
|
|
143
|
+
dependencies: Record<string, JSXRay.Dependency>;
|
|
144
|
+
warnings: JSXRay.Warning<JSXRay.BaseWarning>[];
|
|
76
145
|
};
|
|
77
146
|
}
|
|
78
147
|
|
|
79
148
|
export interface Options {
|
|
149
|
+
/**
|
|
150
|
+
* Maximum tree depth
|
|
151
|
+
*
|
|
152
|
+
* @default 4
|
|
153
|
+
*/
|
|
80
154
|
readonly maxDepth?: number;
|
|
155
|
+
/**
|
|
156
|
+
* Use root package-lock.json. This will have the effect of triggering the Arborist package.
|
|
157
|
+
*
|
|
158
|
+
* @default false for from() API
|
|
159
|
+
* @default true for cwd() API
|
|
160
|
+
*/
|
|
81
161
|
readonly usePackageLock?: boolean;
|
|
82
|
-
|
|
162
|
+
/**
|
|
163
|
+
* Vulnerability strategy name (npm, snyk, node)
|
|
164
|
+
*
|
|
165
|
+
* @default NONE
|
|
166
|
+
*/
|
|
167
|
+
readonly vulnerabilityStrategy: Vuln.Strategy.Kind;
|
|
168
|
+
/**
|
|
169
|
+
* Analyze root package.
|
|
170
|
+
*
|
|
171
|
+
* @default false for from() API
|
|
172
|
+
* @default true for cwd() API
|
|
173
|
+
*/
|
|
83
174
|
readonly forceRootAnalysis?: boolean;
|
|
175
|
+
/**
|
|
176
|
+
* Deeper dependencies analysis with cwd() API.
|
|
177
|
+
*
|
|
178
|
+
* @default false
|
|
179
|
+
*/
|
|
84
180
|
readonly fullLockMode?: boolean;
|
|
85
181
|
}
|
|
86
182
|
}
|