@nodesecure/scanner 3.3.0 → 3.5.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/README.md +97 -95
- package/index.js +1 -1
- package/package.json +19 -19
- package/src/class/dependency.class.js +102 -99
- package/src/depWalker.js +23 -9
- package/src/manifest.js +58 -57
- package/src/npmRegistry.js +74 -68
- package/src/tarball.js +6 -3
- package/src/utils/analyzeDependencies.js +71 -40
- package/types/api.d.ts +1 -1
- package/types/scanner.d.ts +193 -185
package/README.md
CHANGED
|
@@ -1,95 +1,97 @@
|
|
|
1
|
-
# NodeSecure Scanner
|
|
2
|
-

|
|
3
|
-
[](https://github.com/NodeSecure/scanner/commit-activity)
|
|
4
|
-
[](https://github.com/nodejs/security-wg/blob/master/processes/responsible_disclosure_template.md
|
|
5
|
-
)
|
|
6
|
-
[](https://github.com/NodeSecure/scanner/blob/master/LICENSE)
|
|
7
|
-

|
|
8
|
-
|
|
9
|
-
⚡️ Run a static analysis of your module's dependencies.
|
|
10
|
-
|
|
11
|
-
## Requirements
|
|
12
|
-
|
|
13
|
-
- [Node.js](https://nodejs.org/en/) version 16 or higher
|
|
14
|
-
|
|
15
|
-
## Getting Started
|
|
16
|
-
|
|
17
|
-
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).
|
|
18
|
-
|
|
19
|
-
```bash
|
|
20
|
-
$ npm i @nodesecure/scanner
|
|
21
|
-
# or
|
|
22
|
-
$ yarn add @nodesecure/scanner
|
|
23
|
-
```
|
|
24
|
-
|
|
25
|
-
## Usage example
|
|
26
|
-
|
|
27
|
-
```js
|
|
28
|
-
import * as scanner from "@nodesecure/scanner";
|
|
29
|
-
import fs from "fs/promises";
|
|
30
|
-
|
|
31
|
-
// CONSTANTS
|
|
32
|
-
const kPackagesToAnalyze = ["mocha", "cacache", "is-wsl"];
|
|
33
|
-
|
|
34
|
-
const payloads = await Promise.all(
|
|
35
|
-
kPackagesToAnalyze.map((name) => scanner.from(name))
|
|
36
|
-
);
|
|
37
|
-
|
|
38
|
-
const promises = [];
|
|
39
|
-
for (let i = 0; i < kPackagesToAnalyze.length; i++) {
|
|
40
|
-
const data = JSON.stringify(payloads[i], null, 2);
|
|
41
|
-
|
|
42
|
-
promises.push(fs.writeFile(`${kPackagesToAnalyze[i]}.json`, data));
|
|
43
|
-
}
|
|
44
|
-
await Promise.allSettled(promises);
|
|
45
|
-
```
|
|
46
|
-
|
|
47
|
-
## API
|
|
48
|
-
|
|
49
|
-
See `types/api.d.ts` for a complete TypeScript definition.
|
|
50
|
-
|
|
51
|
-
```ts
|
|
52
|
-
function cwd(location: string, options?: Scanner.Options): Promise<Scanner.Payload>;
|
|
53
|
-
function from(packageName: string, options?: Scanner.Options): Promise<Scanner.Payload>;
|
|
54
|
-
function verify(packageName?: string | null): Promise<Scanner.VerifyPayload>;
|
|
55
|
-
```
|
|
56
|
-
|
|
57
|
-
`Options` is described with the following TypeScript interface:
|
|
58
|
-
|
|
59
|
-
```ts
|
|
60
|
-
interface Options {
|
|
61
|
-
readonly maxDepth?: number;
|
|
62
|
-
readonly usePackageLock?: boolean;
|
|
63
|
-
readonly
|
|
64
|
-
readonly
|
|
65
|
-
readonly
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
<!--
|
|
79
|
-
<!--
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
<td align="center"><a href="
|
|
84
|
-
<td align="center"><a href="
|
|
85
|
-
<td align="center"><a href="https://
|
|
86
|
-
|
|
87
|
-
</
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
<!--
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
1
|
+
# NodeSecure Scanner
|
|
2
|
+

|
|
3
|
+
[](https://github.com/NodeSecure/scanner/commit-activity)
|
|
4
|
+
[](https://github.com/nodejs/security-wg/blob/master/processes/responsible_disclosure_template.md
|
|
5
|
+
)
|
|
6
|
+
[](https://github.com/NodeSecure/scanner/blob/master/LICENSE)
|
|
7
|
+

|
|
8
|
+
|
|
9
|
+
⚡️ Run a static analysis of your module's dependencies.
|
|
10
|
+
|
|
11
|
+
## Requirements
|
|
12
|
+
|
|
13
|
+
- [Node.js](https://nodejs.org/en/) version 16 or higher
|
|
14
|
+
|
|
15
|
+
## Getting Started
|
|
16
|
+
|
|
17
|
+
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).
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
$ npm i @nodesecure/scanner
|
|
21
|
+
# or
|
|
22
|
+
$ yarn add @nodesecure/scanner
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Usage example
|
|
26
|
+
|
|
27
|
+
```js
|
|
28
|
+
import * as scanner from "@nodesecure/scanner";
|
|
29
|
+
import fs from "fs/promises";
|
|
30
|
+
|
|
31
|
+
// CONSTANTS
|
|
32
|
+
const kPackagesToAnalyze = ["mocha", "cacache", "is-wsl"];
|
|
33
|
+
|
|
34
|
+
const payloads = await Promise.all(
|
|
35
|
+
kPackagesToAnalyze.map((name) => scanner.from(name))
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
const promises = [];
|
|
39
|
+
for (let i = 0; i < kPackagesToAnalyze.length; i++) {
|
|
40
|
+
const data = JSON.stringify(payloads[i], null, 2);
|
|
41
|
+
|
|
42
|
+
promises.push(fs.writeFile(`${kPackagesToAnalyze[i]}.json`, data));
|
|
43
|
+
}
|
|
44
|
+
await Promise.allSettled(promises);
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## API
|
|
48
|
+
|
|
49
|
+
See `types/api.d.ts` for a complete TypeScript definition.
|
|
50
|
+
|
|
51
|
+
```ts
|
|
52
|
+
function cwd(location: string, options?: Scanner.Options): Promise<Scanner.Payload>;
|
|
53
|
+
function from(packageName: string, options?: Omit<Scanner.Options, "includeDevDeps">): Promise<Scanner.Payload>;
|
|
54
|
+
function verify(packageName?: string | null): Promise<Scanner.VerifyPayload>;
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
`Options` is described with the following TypeScript interface:
|
|
58
|
+
|
|
59
|
+
```ts
|
|
60
|
+
interface Options {
|
|
61
|
+
readonly maxDepth?: number;
|
|
62
|
+
readonly usePackageLock?: boolean;
|
|
63
|
+
readonly includeDevDeps?: boolean;
|
|
64
|
+
readonly vulnerabilityStrategy: Strategy.Kind;
|
|
65
|
+
readonly forceRootAnalysis?: boolean;
|
|
66
|
+
readonly fullLockMode?: boolean;
|
|
67
|
+
}
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## Contributors ✨
|
|
71
|
+
|
|
72
|
+
<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->
|
|
73
|
+
[](#contributors-)
|
|
74
|
+
<!-- ALL-CONTRIBUTORS-BADGE:END -->
|
|
75
|
+
|
|
76
|
+
Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):
|
|
77
|
+
|
|
78
|
+
<!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
|
|
79
|
+
<!-- prettier-ignore-start -->
|
|
80
|
+
<!-- markdownlint-disable -->
|
|
81
|
+
<table>
|
|
82
|
+
<tr>
|
|
83
|
+
<td align="center"><a href="https://www.linkedin.com/in/thomas-gentilhomme/"><img src="https://avatars.githubusercontent.com/u/4438263?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Gentilhomme</b></sub></a><br /><a href="https://github.com/NodeSecure/scanner/commits?author=fraxken" title="Code">💻</a> <a href="https://github.com/NodeSecure/scanner/commits?author=fraxken" title="Documentation">📖</a> <a href="https://github.com/NodeSecure/scanner/pulls?q=is%3Apr+reviewed-by%3Afraxken" title="Reviewed Pull Requests">👀</a> <a href="#security-fraxken" title="Security">🛡️</a> <a href="https://github.com/NodeSecure/scanner/issues?q=author%3Afraxken" title="Bug reports">🐛</a></td>
|
|
84
|
+
<td align="center"><a href="http://tonygo.dev"><img src="https://avatars.githubusercontent.com/u/22824417?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Tony Gorez</b></sub></a><br /><a href="https://github.com/NodeSecure/scanner/commits?author=tony-go" title="Code">💻</a> <a href="https://github.com/NodeSecure/scanner/commits?author=tony-go" title="Documentation">📖</a> <a href="https://github.com/NodeSecure/scanner/pulls?q=is%3Apr+reviewed-by%3Atony-go" title="Reviewed Pull Requests">👀</a> <a href="https://github.com/NodeSecure/scanner/issues?q=author%3Atony-go" title="Bug reports">🐛</a></td>
|
|
85
|
+
<td align="center"><a href="https://mickaelcroquet.fr"><img src="https://avatars.githubusercontent.com/u/23740372?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Haze</b></sub></a><br /><a href="https://github.com/NodeSecure/scanner/commits?author=CroquetMickael" title="Code">💻</a></td>
|
|
86
|
+
<td align="center"><a href="https://github.com/mbalabash"><img src="https://avatars.githubusercontent.com/u/16868922?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Maksim Balabash</b></sub></a><br /><a href="https://github.com/NodeSecure/scanner/commits?author=mbalabash" title="Code">💻</a></td>
|
|
87
|
+
<td align="center"><a href="https://dev.to/antoinecoulon"><img src="https://avatars.githubusercontent.com/u/43391199?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Antoine Coulon</b></sub></a><br /><a href="https://github.com/NodeSecure/scanner/commits?author=antoine-coulon" title="Code">💻</a> <a href="#security-antoine-coulon" title="Security">🛡️</a></td>
|
|
88
|
+
</tr>
|
|
89
|
+
</table>
|
|
90
|
+
|
|
91
|
+
<!-- markdownlint-restore -->
|
|
92
|
+
<!-- prettier-ignore-end -->
|
|
93
|
+
|
|
94
|
+
<!-- ALL-CONTRIBUTORS-LIST:END -->
|
|
95
|
+
|
|
96
|
+
## License
|
|
97
|
+
MIT
|
package/index.js
CHANGED
|
@@ -16,7 +16,7 @@ import Logger from "./src/class/logger.class.js";
|
|
|
16
16
|
import * as tarball from "./src/tarball.js";
|
|
17
17
|
|
|
18
18
|
// CONSTANTS
|
|
19
|
-
const kDefaultCwdOptions = { forceRootAnalysis: true, usePackageLock: true };
|
|
19
|
+
const kDefaultCwdOptions = { forceRootAnalysis: true, usePackageLock: true, includeDevDeps: false };
|
|
20
20
|
|
|
21
21
|
export async function cwd(location = process.cwd(), options = {}, logger = new Logger()) {
|
|
22
22
|
const finalizedOptions = Object.assign({ location }, kDefaultCwdOptions, options);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nodesecure/scanner",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.5.0",
|
|
4
4
|
"description": "A package API to run a static analysis of your module's dependencies.",
|
|
5
5
|
"exports": "./index.js",
|
|
6
6
|
"engines": {
|
|
@@ -48,39 +48,39 @@
|
|
|
48
48
|
},
|
|
49
49
|
"homepage": "https://github.com/NodeSecure/scanner#readme",
|
|
50
50
|
"devDependencies": {
|
|
51
|
-
"@nodesecure/eslint-config": "^1.
|
|
51
|
+
"@nodesecure/eslint-config": "^1.4.0",
|
|
52
52
|
"@slimio/is": "^1.5.1",
|
|
53
|
-
"@small-tech/esm-tape-runner": "^
|
|
54
|
-
"@small-tech/tap-monkey": "^1.
|
|
55
|
-
"@types/node": "^17.0.
|
|
56
|
-
"c8": "^7.11.
|
|
53
|
+
"@small-tech/esm-tape-runner": "^2.0.0",
|
|
54
|
+
"@small-tech/tap-monkey": "^1.4.0",
|
|
55
|
+
"@types/node": "^17.0.39",
|
|
56
|
+
"c8": "^7.11.3",
|
|
57
57
|
"cross-env": "^7.0.3",
|
|
58
|
-
"dotenv": "^
|
|
59
|
-
"eslint": "^8.
|
|
58
|
+
"dotenv": "^16.0.1",
|
|
59
|
+
"eslint": "^8.17.0",
|
|
60
60
|
"get-folder-size": "^3.1.0",
|
|
61
|
-
"pkg-ok": "^
|
|
62
|
-
"sinon": "^
|
|
61
|
+
"pkg-ok": "^3.0.0",
|
|
62
|
+
"sinon": "^14.0.0",
|
|
63
63
|
"snap-shot-core": "^10.2.4",
|
|
64
|
-
"tape": "^5.5.
|
|
64
|
+
"tape": "^5.5.3"
|
|
65
65
|
},
|
|
66
66
|
"dependencies": {
|
|
67
67
|
"@nodesecure/flags": "^2.2.0",
|
|
68
68
|
"@nodesecure/fs-walk": "^1.0.0",
|
|
69
|
-
"@nodesecure/i18n": "^1.
|
|
70
|
-
"@nodesecure/js-x-ray": "^4.
|
|
69
|
+
"@nodesecure/i18n": "^1.3.0",
|
|
70
|
+
"@nodesecure/js-x-ray": "^4.4.0",
|
|
71
71
|
"@nodesecure/npm-registry-sdk": "^1.3.0",
|
|
72
72
|
"@nodesecure/ntlp": "^2.1.0",
|
|
73
73
|
"@nodesecure/utils": "^1.0.0",
|
|
74
|
-
"@nodesecure/vuln": "^1.
|
|
75
|
-
"@npm/types": "^1.0.
|
|
76
|
-
"@npmcli/arborist": "^
|
|
74
|
+
"@nodesecure/vuln": "^1.7.0",
|
|
75
|
+
"@npm/types": "^1.0.2",
|
|
76
|
+
"@npmcli/arborist": "^5.2.1",
|
|
77
77
|
"@slimio/lock": "^1.0.0",
|
|
78
|
-
"builtins": "^
|
|
78
|
+
"builtins": "^5.0.1",
|
|
79
79
|
"combine-async-iterators": "^2.0.1",
|
|
80
80
|
"itertools": "^1.7.1",
|
|
81
81
|
"lodash.difference": "^4.5.0",
|
|
82
|
-
"pacote": "^
|
|
83
|
-
"semver": "^7.3.
|
|
82
|
+
"pacote": "^13.6.0",
|
|
83
|
+
"semver": "^7.3.7"
|
|
84
84
|
},
|
|
85
85
|
"type": "module"
|
|
86
86
|
}
|
|
@@ -1,99 +1,102 @@
|
|
|
1
|
-
export default class Dependency {
|
|
2
|
-
#flags = new Set();
|
|
3
|
-
#parent = null;
|
|
4
|
-
|
|
5
|
-
constructor(name, version, parent = null) {
|
|
6
|
-
this.gitUrl = null;
|
|
7
|
-
this.dependencyCount = 0;
|
|
8
|
-
this.warnings = [];
|
|
9
|
-
this.name = name;
|
|
10
|
-
this.version = version;
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
|
|
1
|
+
export default class Dependency {
|
|
2
|
+
#flags = new Set();
|
|
3
|
+
#parent = null;
|
|
4
|
+
|
|
5
|
+
constructor(name, version, parent = null) {
|
|
6
|
+
this.gitUrl = null;
|
|
7
|
+
this.dependencyCount = 0;
|
|
8
|
+
this.warnings = [];
|
|
9
|
+
this.name = name;
|
|
10
|
+
this.version = version;
|
|
11
|
+
this.dev = false;
|
|
12
|
+
|
|
13
|
+
if (parent !== null) {
|
|
14
|
+
parent.dependencyCount++;
|
|
15
|
+
}
|
|
16
|
+
this.#parent = parent;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
get fullName() {
|
|
20
|
+
return `${this.name} ${this.version}`;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
get flags() {
|
|
24
|
+
return [...this.#flags];
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
get parent() {
|
|
28
|
+
return this.#parent === null ? {} : { [this.#parent.name]: this.#parent.version };
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
addFlag(flagName, predicate = true) {
|
|
32
|
+
if (typeof flagName !== "string") {
|
|
33
|
+
throw new TypeError("flagName argument must be typeof string");
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if (predicate) {
|
|
37
|
+
if (flagName === "hasDependencies" && this.#parent !== null) {
|
|
38
|
+
this.#parent.addFlag("hasIndirectDependencies");
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
this.#flags.add(flagName);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
isGit(url) {
|
|
46
|
+
this.#flags.add("isGit");
|
|
47
|
+
if (typeof url === "string") {
|
|
48
|
+
this.gitUrl = url;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return this;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
exportAsPlainObject(customId) {
|
|
55
|
+
if (this.warnings.length > 0) {
|
|
56
|
+
this.addFlag("hasWarnings");
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return {
|
|
60
|
+
versions: {
|
|
61
|
+
[this.version]: {
|
|
62
|
+
id: typeof customId === "number" ? customId : Dependency.currentId++,
|
|
63
|
+
usedBy: this.parent,
|
|
64
|
+
isDevDependency: this.dev,
|
|
65
|
+
flags: this.flags,
|
|
66
|
+
description: "",
|
|
67
|
+
size: 0,
|
|
68
|
+
author: {},
|
|
69
|
+
warnings: this.warnings,
|
|
70
|
+
composition: {
|
|
71
|
+
extensions: [],
|
|
72
|
+
files: [],
|
|
73
|
+
minified: [],
|
|
74
|
+
unused: [],
|
|
75
|
+
missing: [],
|
|
76
|
+
required_files: [],
|
|
77
|
+
required_nodejs: [],
|
|
78
|
+
required_thirdparty: [],
|
|
79
|
+
required_subpath: []
|
|
80
|
+
},
|
|
81
|
+
license: "unkown license",
|
|
82
|
+
gitUrl: this.gitUrl
|
|
83
|
+
}
|
|
84
|
+
},
|
|
85
|
+
vulnerabilities: [],
|
|
86
|
+
metadata: {
|
|
87
|
+
dependencyCount: this.dependencyCount,
|
|
88
|
+
publishedCount: 0,
|
|
89
|
+
lastUpdateAt: null,
|
|
90
|
+
lastVersion: null,
|
|
91
|
+
hasManyPublishers: false,
|
|
92
|
+
hasReceivedUpdateInOneYear: true,
|
|
93
|
+
homepage: null,
|
|
94
|
+
author: {},
|
|
95
|
+
publishers: [],
|
|
96
|
+
maintainers: []
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
Dependency.currentId = 1;
|
package/src/depWalker.js
CHANGED
|
@@ -75,13 +75,15 @@ export async function* searchDeepDependencies(packageName, gitURL, options) {
|
|
|
75
75
|
yield current;
|
|
76
76
|
}
|
|
77
77
|
|
|
78
|
-
export async function* deepReadEdges(currentPackageName,
|
|
78
|
+
export async function* deepReadEdges(currentPackageName, options) {
|
|
79
|
+
const { to, parent, exclude, fullLockMode, includeDevDeps } = options;
|
|
79
80
|
const { version, integrity = to.integrity } = to.package;
|
|
80
81
|
|
|
81
82
|
const updatedVersion = version === "*" || typeof version === "undefined" ? "latest" : version;
|
|
82
83
|
const current = new Dependency(currentPackageName, updatedVersion, parent);
|
|
84
|
+
current.dev = to.dev;
|
|
83
85
|
|
|
84
|
-
if (fullLockMode) {
|
|
86
|
+
if (fullLockMode && !includeDevDeps) {
|
|
85
87
|
const { deprecated, _integrity, ...pkg } = await pacote.manifest(`${currentPackageName}@${updatedVersion}`, {
|
|
86
88
|
...NPM_TOKEN,
|
|
87
89
|
registry: getLocalRegistryURL(),
|
|
@@ -96,7 +98,7 @@ export async function* deepReadEdges(currentPackageName, { to, parent, exclude,
|
|
|
96
98
|
current.addFlag("hasDependencies", to.edgesOut.size > 0);
|
|
97
99
|
|
|
98
100
|
for (const [packageName, { to: toNode }] of to.edgesOut) {
|
|
99
|
-
if (toNode === null || toNode.dev) {
|
|
101
|
+
if (toNode === null || (!includeDevDeps && toNode.dev)) {
|
|
100
102
|
continue;
|
|
101
103
|
}
|
|
102
104
|
const cleanName = `${packageName}@${toNode.package.version}`;
|
|
@@ -113,7 +115,11 @@ export async function* deepReadEdges(currentPackageName, { to, parent, exclude,
|
|
|
113
115
|
}
|
|
114
116
|
|
|
115
117
|
export async function* getRootDependencies(manifest, options) {
|
|
116
|
-
const {
|
|
118
|
+
const {
|
|
119
|
+
maxDepth = 4, exclude,
|
|
120
|
+
usePackageLock, fullLockMode, includeDevDeps,
|
|
121
|
+
location
|
|
122
|
+
} = options;
|
|
117
123
|
|
|
118
124
|
const { dependencies, customResolvers } = mergeDependencies(manifest, void 0);
|
|
119
125
|
const parent = new Dependency(manifest.name, manifest.version);
|
|
@@ -137,9 +143,10 @@ export async function* getRootDependencies(manifest, options) {
|
|
|
137
143
|
}
|
|
138
144
|
|
|
139
145
|
iterators = [
|
|
140
|
-
...iter
|
|
146
|
+
...iter
|
|
147
|
+
.filter(tree.edgesOut.entries(), ([, { to }]) => to !== null && (includeDevDeps ? true : (!to.dev || to.isWorkspace)))
|
|
141
148
|
.map(([packageName, { to }]) => [packageName, to.isWorkspace ? to.target : to])
|
|
142
|
-
.map(([packageName, to]) => deepReadEdges(packageName, { to, parent, fullLockMode, exclude }))
|
|
149
|
+
.map(([packageName, to]) => deepReadEdges(packageName, { to, parent, fullLockMode, includeDevDeps, exclude }))
|
|
143
150
|
];
|
|
144
151
|
}
|
|
145
152
|
else {
|
|
@@ -178,6 +185,7 @@ export async function depWalker(manifest, options = {}, logger = new Logger()) {
|
|
|
178
185
|
const {
|
|
179
186
|
forceRootAnalysis = false,
|
|
180
187
|
usePackageLock = false,
|
|
188
|
+
includeDevDeps = false,
|
|
181
189
|
fullLockMode = false,
|
|
182
190
|
maxDepth,
|
|
183
191
|
location,
|
|
@@ -210,9 +218,9 @@ export async function depWalker(manifest, options = {}, logger = new Logger()) {
|
|
|
210
218
|
const tarballLocker = new Lock({ maxConcurrent: 5 });
|
|
211
219
|
tarballLocker.on("freeOne", () => logger.tick(ScannerLoggerEvents.analysis.tarball));
|
|
212
220
|
|
|
213
|
-
const rootDepsOptions = { maxDepth, exclude, usePackageLock, fullLockMode, location };
|
|
221
|
+
const rootDepsOptions = { maxDepth, exclude, usePackageLock, fullLockMode, includeDevDeps, location };
|
|
214
222
|
for await (const currentDep of getRootDependencies(manifest, rootDepsOptions)) {
|
|
215
|
-
const { name, version } = currentDep;
|
|
223
|
+
const { name, version, dev } = currentDep;
|
|
216
224
|
const current = currentDep.exportAsPlainObject(name === manifest.name ? 0 : void 0);
|
|
217
225
|
let proceedDependencyAnalysis = true;
|
|
218
226
|
|
|
@@ -234,6 +242,11 @@ export async function depWalker(manifest, options = {}, logger = new Logger()) {
|
|
|
234
242
|
dependencies.set(name, current);
|
|
235
243
|
}
|
|
236
244
|
|
|
245
|
+
// If the dependency is a DevDependencies we ignore it.
|
|
246
|
+
if (dev) {
|
|
247
|
+
continue;
|
|
248
|
+
}
|
|
249
|
+
|
|
237
250
|
if (proceedDependencyAnalysis) {
|
|
238
251
|
logger.tick(ScannerLoggerEvents.analysis.tree);
|
|
239
252
|
|
|
@@ -270,7 +283,8 @@ export async function depWalker(manifest, options = {}, logger = new Logger()) {
|
|
|
270
283
|
|
|
271
284
|
const { hydratePayloadDependencies, strategy } = await vuln.setStrategy(vulnerabilityStrategy);
|
|
272
285
|
await hydratePayloadDependencies(dependencies, {
|
|
273
|
-
useStandardFormat: true
|
|
286
|
+
useStandardFormat: true,
|
|
287
|
+
path: location
|
|
274
288
|
});
|
|
275
289
|
|
|
276
290
|
payload.vulnerabilityStrategy = strategy;
|