scanoss 0.2.26 → 0.3.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.
Files changed (158) hide show
  1. package/.github/workflows/reuse.yml +15 -0
  2. package/.github/workflows/scanoss.yml +24 -0
  3. package/.gitignore +0 -1
  4. package/.idea/.gitignore +5 -0
  5. package/.idea/codeStyles/Project.xml +61 -0
  6. package/.idea/codeStyles/codeStyleConfig.xml +5 -0
  7. package/.idea/inspectionProfiles/Project_Default.xml +6 -0
  8. package/.idea/modules.xml +8 -0
  9. package/.idea/scanoss.js.iml +12 -0
  10. package/.idea/vcs.xml +6 -0
  11. package/.idea/workspace.xml +366 -0
  12. package/.nyc_output/a25d3ac4-ee71-4c5e-926e-3a17714555cd.json +1 -0
  13. package/.nyc_output/processinfo/a25d3ac4-ee71-4c5e-926e-3a17714555cd.json +1 -0
  14. package/.nyc_output/processinfo/index.json +1 -0
  15. package/.reuse/dep5 +16 -0
  16. package/LICENSES/CC0-1.0.txt +121 -0
  17. package/LICENSES/MIT.txt +9 -0
  18. package/README.md +9 -0
  19. package/build/main/bin/cli-bin.js +5 -3
  20. package/build/main/commands/dep.js +1 -2
  21. package/build/main/commands/fingerprint.js +20 -12
  22. package/build/main/commands/helpers.js +1 -2
  23. package/build/main/commands/scan.js +7 -2
  24. package/build/main/index.js +1 -2
  25. package/build/main/lib/dependencies/DependencyScanner.d.ts +1 -1
  26. package/build/main/lib/dependencies/DependencyScanner.js +23 -12
  27. package/build/main/lib/dependencies/DependencyScannerCfg.js +1 -2
  28. package/build/main/lib/dependencies/DependencyTypes.js +0 -1
  29. package/build/main/lib/dependencies/LocalDependency/DependencyTypes.js +0 -1
  30. package/build/main/lib/dependencies/LocalDependency/LocalDependency.js +3 -2
  31. package/build/main/lib/dependencies/LocalDependency/parsers/golangParser.d.ts +1 -0
  32. package/build/main/lib/dependencies/LocalDependency/parsers/golangParser.js +50 -16
  33. package/build/main/lib/dependencies/LocalDependency/parsers/mavenParser.js +130 -15
  34. package/build/main/lib/dependencies/LocalDependency/parsers/npmParser.d.ts +10 -0
  35. package/build/main/lib/dependencies/LocalDependency/parsers/npmParser.js +146 -10
  36. package/build/main/lib/dependencies/LocalDependency/parsers/pyParser.js +1 -2
  37. package/build/main/lib/dependencies/LocalDependency/parsers/rubyParser.js +1 -2
  38. package/build/main/lib/dependencies/LocalDependency/parsers/utils.js +1 -2
  39. package/build/main/lib/filters/defaultFilter.js +1 -2
  40. package/build/main/lib/filters/filtering.js +1 -2
  41. package/build/main/lib/grpc/GrpcDependencyService.js +1 -2
  42. package/build/main/lib/grpc/scanoss/api/components/v2/scanoss-components_grpc_pb.d.ts +62 -0
  43. package/build/main/lib/grpc/scanoss/api/components/v2/scanoss-components_grpc_pb.js +128 -0
  44. package/build/main/lib/grpc/scanoss/api/components/v2/scanoss-components_pb.d.ts +1 -0
  45. package/build/main/lib/grpc/scanoss/api/components/v2/scanoss-components_pb.js +1403 -0
  46. package/build/main/lib/scanner/Dispatcher/DispatchableItem.d.ts +14 -5
  47. package/build/main/lib/scanner/Dispatcher/DispatchableItem.js +30 -10
  48. package/build/main/lib/scanner/Dispatcher/Dispatcher.d.ts +2 -2
  49. package/build/main/lib/scanner/Dispatcher/Dispatcher.js +10 -15
  50. package/build/main/lib/scanner/Dispatcher/DispatcherResponse.js +1 -2
  51. package/build/main/lib/scanner/Dispatcher/GlobalControllerAborter.js +1 -2
  52. package/build/main/lib/scanner/Scannable/ScannableItem.js +1 -2
  53. package/build/main/lib/scanner/Scanner.js +13 -9
  54. package/build/main/lib/scanner/ScannerCfg.js +2 -3
  55. package/build/main/lib/scanner/ScannerQueue.d.ts +3 -0
  56. package/build/main/lib/scanner/ScannerQueue.js +8 -0
  57. package/build/main/lib/scanner/ScannerTypes.d.ts +9 -2
  58. package/build/main/lib/scanner/ScannerTypes.js +8 -3
  59. package/build/main/lib/scanner/WfpProvider/FingerprintPackage.d.ts +9 -0
  60. package/build/main/lib/scanner/WfpProvider/FingerprintPackage.js +31 -0
  61. package/build/main/lib/scanner/WfpProvider/WfpCalculator/WfpCalculator.js +178 -21
  62. package/build/main/lib/scanner/WfpProvider/WfpCalculator/Winnower.d.ts +3 -0
  63. package/build/main/lib/scanner/WfpProvider/WfpCalculator/Winnower.js +211 -0
  64. package/build/main/lib/scanner/WfpProvider/WfpProvider.d.ts +2 -2
  65. package/build/main/lib/scanner/WfpProvider/WfpProvider.js +6 -7
  66. package/build/main/lib/scanner/WfpProvider/WfpSplitter/WfpSplitter.js +1 -2
  67. package/build/main/lib/tree/File.js +1 -2
  68. package/build/main/lib/tree/Folder.js +1 -2
  69. package/build/main/lib/tree/Node.js +1 -2
  70. package/build/main/lib/tree/Tree.js +1 -2
  71. package/build/module/bin/cli-bin.js +5 -2
  72. package/build/module/commands/fingerprint.js +25 -16
  73. package/build/module/commands/scan.js +8 -2
  74. package/build/module/lib/dependencies/DependencyScanner.d.ts +1 -1
  75. package/build/module/lib/dependencies/DependencyScanner.js +23 -11
  76. package/build/module/lib/dependencies/LocalDependency/LocalDependency.js +5 -3
  77. package/build/module/lib/dependencies/LocalDependency/parsers/golangParser.d.ts +1 -0
  78. package/build/module/lib/dependencies/LocalDependency/parsers/golangParser.js +47 -14
  79. package/build/module/lib/dependencies/LocalDependency/parsers/mavenParser.js +130 -14
  80. package/build/module/lib/dependencies/LocalDependency/parsers/npmParser.d.ts +10 -0
  81. package/build/module/lib/dependencies/LocalDependency/parsers/npmParser.js +140 -8
  82. package/build/module/lib/grpc/scanoss/api/components/v2/scanoss-components_grpc_pb.d.ts +62 -0
  83. package/build/module/lib/grpc/scanoss/api/components/v2/scanoss-components_grpc_pb.js +128 -0
  84. package/build/module/lib/grpc/scanoss/api/components/v2/scanoss-components_pb.d.ts +1 -0
  85. package/build/module/lib/grpc/scanoss/api/components/v2/scanoss-components_pb.js +1403 -0
  86. package/build/module/lib/scanner/Dispatcher/DispatchableItem.d.ts +14 -5
  87. package/build/module/lib/scanner/Dispatcher/DispatchableItem.js +32 -10
  88. package/build/module/lib/scanner/Dispatcher/Dispatcher.d.ts +2 -2
  89. package/build/module/lib/scanner/Dispatcher/Dispatcher.js +10 -14
  90. package/build/module/lib/scanner/Scanner.js +12 -8
  91. package/build/module/lib/scanner/ScannerCfg.js +2 -2
  92. package/build/module/lib/scanner/ScannerQueue.d.ts +3 -0
  93. package/build/module/lib/scanner/ScannerQueue.js +4 -0
  94. package/build/module/lib/scanner/ScannerTypes.d.ts +9 -2
  95. package/build/module/lib/scanner/ScannerTypes.js +7 -1
  96. package/build/module/lib/scanner/WfpProvider/FingerprintPackage.d.ts +9 -0
  97. package/build/module/lib/scanner/WfpProvider/FingerprintPackage.js +30 -0
  98. package/build/module/lib/scanner/WfpProvider/WfpCalculator/WfpCalculator.js +178 -20
  99. package/build/module/lib/scanner/WfpProvider/WfpCalculator/Winnower.d.ts +3 -0
  100. package/build/module/lib/scanner/WfpProvider/WfpCalculator/Winnower.js +211 -0
  101. package/build/module/lib/scanner/WfpProvider/WfpProvider.d.ts +2 -2
  102. package/build/module/lib/scanner/WfpProvider/WfpProvider.js +6 -6
  103. package/build/tsconfig.module.tsbuildinfo +1 -1
  104. package/build/tsconfig.tsbuildinfo +1 -1
  105. package/package.json +6 -17
  106. package/src/bin/cli-bin.ts +4 -1
  107. package/src/commands/fingerprint.ts +26 -17
  108. package/src/commands/scan.ts +16 -3
  109. package/src/lib/dependencies/DependencyScanner.ts +20 -13
  110. package/src/lib/dependencies/LocalDependency/LocalDependency.ts +8 -2
  111. package/src/lib/dependencies/LocalDependency/parsers/golangParser.ts +67 -15
  112. package/src/lib/dependencies/LocalDependency/parsers/mavenParser.ts +143 -16
  113. package/src/lib/dependencies/LocalDependency/parsers/npmParser.ts +182 -7
  114. package/src/lib/scanner/Dispatcher/DispatchableItem.ts +45 -11
  115. package/src/lib/scanner/Dispatcher/Dispatcher.ts +11 -14
  116. package/src/lib/scanner/Scanner.ts +17 -13
  117. package/src/lib/scanner/ScannerCfg.ts +2 -1
  118. package/src/lib/scanner/ScannerTypes.ts +10 -2
  119. package/src/lib/scanner/WfpProvider/{FingerprintPacket.ts → FingerprintPackage.ts} +4 -14
  120. package/src/lib/scanner/WfpProvider/WfpCalculator/WfpCalculator.ts +177 -20
  121. package/src/lib/scanner/WfpProvider/WfpProvider.ts +5 -5
  122. package/tests/WfpCalculator.spec.ts +103 -0
  123. package/tests/data/dependencies/Gemfile/1/Gemfile +6 -0
  124. package/tests/data/dependencies/Gemfile/1/Gemfile~ +0 -0
  125. package/tests/data/dependencies/Gemfile/2/Gemfile +3 -0
  126. package/tests/data/dependencies/Gemfile/2/Gemfile~ +6 -0
  127. package/tests/data/dependencies/Gemfile/3/Gemfile +7 -0
  128. package/tests/data/dependencies/Gemfile/3/Gemfile~ +6 -0
  129. package/tests/data/dependencies/Gemfile/4/Gemfile +31 -0
  130. package/tests/data/dependencies/Gemfile/4/Gemfile~ +7 -0
  131. package/tests/data/dependencies/Gemfile.lock/1/Gemfile.lock +180 -0
  132. package/tests/data/dependencies/Gemfile.lock/2/Gemfile.lock +60 -0
  133. package/tests/data/dependencies/Gemfile.lock/2/Gemfile.lock~ +0 -0
  134. package/tests/data/dependencies/go.sum/1/go.sum +119 -0
  135. package/tests/data/dependencies/go.sum/depJSON.sh +23 -0
  136. package/tests/data/dependencies/package-lock/1/package-lock.json +715 -0
  137. package/tests/data/dependencies/package-lock/2/package-lock.json +32069 -0
  138. package/tests/data/dependencies/package-lock/3/package-lock.json +9013 -0
  139. package/tests/data/dependencies/pom.xml/1/pom.xml +162 -0
  140. package/tests/data/dependencies/yarn-lock/generate_expected_output.sh +4 -0
  141. package/tests/data/dependencies/yarn-lock/v1/yarn.lock +50 -0
  142. package/tests/data/dependencies/yarn-lock/v1/yarn.lock-expected +13 -0
  143. package/tests/data/dependencies/yarn-lock/v1-complex/yarn.lock +27 -0
  144. package/tests/data/dependencies/yarn-lock/v1-complex/yarn.lock-expected +8 -0
  145. package/tests/data/dependencies/yarn-lock/v1-complex2/yarn.lock +220 -0
  146. package/tests/data/dependencies/yarn-lock/v2/yarn.lock +31 -0
  147. package/tests/data/dependencies/yarn-lock/v2/yarn.lock-expected +57 -0
  148. package/tests/data/dependencies/yarn-lock/v2-local/yarn.lock +11 -0
  149. package/tests/data/dependencies/yarn-lock/v2-local/yarn.lock-expected +27204 -0
  150. package/tests/data/scanner/file1.c +41 -0
  151. package/tests/data/scanner/file2.go +87 -0
  152. package/tests/dependencies/golangParser.goModParser.specs.ts +146 -0
  153. package/tests/dependencies/npmParser.spec.ts +133 -0
  154. package/tsconfig.json +4 -3
  155. package/yarn.lock +4596 -5321
  156. package/examples/defaultFilter.json +0 -203
  157. package/package-lock.json +0 -18588
  158. package/src/lib/scanner/Winnower/WinnowerExtractor.ts +0 -37
@@ -16,7 +16,6 @@ export function packageParser(fileContent: string, filePath: string): ILocalDepe
16
16
  const o = JSON.parse(fileContent);
17
17
  let devDeps = Object.keys(o.devDependencies || {});
18
18
  let deps = Object.keys(o.dependencies || {});
19
- let listDeps = [...deps, ...devDeps];
20
19
 
21
20
  for(const name of deps){
22
21
  const purlString = new PackageURL(PURL_TYPE, undefined, name, undefined, undefined, undefined).toString();
@@ -34,18 +33,194 @@ export function packageParser(fileContent: string, filePath: string): ILocalDepe
34
33
 
35
34
  // Parse a package-lock.json file from node projects
36
35
  // See reference on: https://docs.npmjs.com/cli/v8/configuring-npm/package-json
37
- const MANIFEST_FILE_1 = 'package-lock.json';
38
36
  export function packagelockParser(fileContent: string, filePath: string): ILocalDependency {
39
37
 
40
38
  const results: ILocalDependency = {file: filePath, purls: []};
41
- if(path.basename(filePath) != MANIFEST_FILE_1)
39
+
40
+ if(path.basename(filePath) != 'package-lock.json')
42
41
  return results;
43
42
 
44
- const o = JSON.parse(fileContent).dependencies;
45
- for (const [key, value] of Object.entries(o)) {
43
+ const packages = JSON.parse(fileContent)?.packages;
44
+
45
+ if(!packages) return results;
46
+
47
+ for (const [key, value] of Object.entries(packages)) {
46
48
  if(!key) continue;
47
- let purl = new PackageURL(PURL_TYPE, undefined, key,value['version'], undefined, undefined).toString();
48
- results.purls.push({purl});
49
+
50
+ const keySplit = key.split("/")
51
+ const depName = keySplit[keySplit.length-1]
52
+
53
+ let purl = new PackageURL(PURL_TYPE, undefined, depName,undefined, undefined, undefined).toString();
54
+ let req = value['version'];
55
+ results.purls.push({purl: purl, requirement: req});
49
56
  }
57
+
58
+ return results;
59
+ }
60
+
61
+
62
+
63
+ export function yarnLockParser(fileContent: string, filePath: string): ILocalDependency {
64
+ const results: ILocalDependency = {file: filePath, purls: []};
65
+
66
+ if(path.basename(filePath) != 'yarn.lock')
50
67
  return results;
68
+
69
+ const yarnVersion = yarnLockRecognizeVersion(fileContent)
70
+ if (yarnVersion === YarnLockVersionEnum.V1) return yarnLockV1Parser(fileContent, filePath)
71
+ else if (yarnVersion === YarnLockVersionEnum.V2) return yarnLockV2Parser(fileContent, filePath)
72
+
73
+ return results;
74
+ }
75
+
76
+ enum YarnLockVersionEnum {
77
+ "V1" ,
78
+ "V2",
79
+ UnknownYarnLockFormat
80
+ }
81
+
82
+ /*
83
+ The start of v1 file has this:
84
+ # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
85
+ # yarn lockfile v1
86
+
87
+ The start of v2 file has this:
88
+ # This file is generated by running "yarn install" inside your project.
89
+ # Manual changes might be lost - proceed with caution!
90
+
91
+ __metadata:
92
+ */
93
+ export function yarnLockRecognizeVersion(fileContent: string): YarnLockVersionEnum {
94
+
95
+ const yarn = fileContent.split("\n", 10) //Check only the first 10 lines;
96
+ for (const line of yarn) {
97
+ if ( line.includes('__metadata:') ) return YarnLockVersionEnum.V2
98
+ if ( line.includes('yarn lockfile v1') ) return YarnLockVersionEnum.V1
99
+ }
100
+ return YarnLockVersionEnum.UnknownYarnLockFormat
101
+ }
102
+
103
+ export function yarnLockV1Parser(fileContent: string, filePath: string): ILocalDependency {
104
+
105
+ const results: ILocalDependency = {file: filePath, purls: []};
106
+
107
+ //Yield an array with each element is a dependency
108
+ /*
109
+ "@babel/core@^7.1.0", "@babel/core@^7.3.4":
110
+ version "7.3.4"
111
+ resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.3.4.tgz#921a5a13746c21e32445bf0798680e9d11a6530b"
112
+ integrity sha512-jRsuseXBo9pN197KnDwhhaaBzyZr2oIcLHHTt2oDdQrej5Qp57dCCJafWx5ivU8/alEYDpssYqv1MUqcxwQlrA==
113
+ dependencies:
114
+ "@babel/code-frame" "^7.0.0"
115
+ "@babel/generator" "^7.3.4"
116
+ */
117
+ const yl_dependencies = fileContent.split("\n\n");
118
+
119
+ for (const yl_dependency of yl_dependencies) {
120
+
121
+
122
+
123
+ const dependencyData: Record<string, string> = {}
124
+ const topRequirements = [];
125
+
126
+ const dep_lines = yl_dependency.split("\n");
127
+ if (dep_lines.every((line) => line.trim().startsWith("#") == true)) continue //All lines are coments
128
+ if (dep_lines.every((line) => line.trim() == "")) continue //All lines are empty lines
129
+
130
+ for (const dep_line of dep_lines) {
131
+
132
+ // Clean comments and empty lines
133
+ const trimmed = dep_line.trim();
134
+ const comment = trimmed.startsWith('#');
135
+ if (!trimmed || comment) continue
136
+
137
+ // Do nothing with it's own dependencies
138
+ // "@babel/code-frame" "^7.0.0"
139
+ // "@babel/generator" "^7.3.4"
140
+ if (dep_line.startsWith(' '.repeat(4))) {}
141
+
142
+ // version "7.3.4"
143
+ // resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.3.4.tgz#921a5a13746c21e32445bf0798680e9d11a6530b"
144
+ // integrity sha512-jRsuseXBo9pN197KnDwhhaaBzyZr2oIcLHHTt2oDdQrej5Qp57dCCJafWx5ivU8/alEYDpssYqv1MUqcxwQlrA==
145
+ // dependencies:
146
+ else if (dep_line.startsWith(' '.repeat(2))) {
147
+ const dep = trimmed.split(" ")
148
+ const key = dep[0].trim();
149
+ if (key !== "dependencies:") {
150
+ dependencyData[key] = dep[1].replace(/"|'/g, "");
151
+ }
152
+ }
153
+
154
+ // the first line of a dependency has the name and requirements
155
+ //"@babel/core@^7.1.0", "@babel/core@^7.3.4":
156
+ else if (!dep_line.startsWith(' ')){
157
+ const dep = dep_line.replace(/:/g, "").split(",");
158
+ const requirements = dep.map(line => line.trim().replace(/"|'/g, ""));
159
+
160
+ for (const req of requirements) {
161
+
162
+ const atIndex = req.lastIndexOf("@")
163
+
164
+ let constraint = req.slice(atIndex+1) // gets ^7.1.0
165
+ constraint = constraint.replace(/"|'/g, "");
166
+
167
+ const ns_name = req.slice(0, atIndex)
168
+
169
+ let ns = '';
170
+ let name = ns_name;
171
+ if (ns_name.includes("/")) {
172
+ const slashIndex = req.lastIndexOf("/")
173
+ ns = ns_name.slice(0,slashIndex);
174
+ name = ns_name.slice(slashIndex+1)
175
+ }
176
+
177
+ topRequirements.push({constraint: constraint, ns: ns, name: name });
178
+ }
179
+
180
+ }
181
+
182
+
183
+ }
184
+
185
+ //Make sure that name and namespace are equal for the same dependency
186
+ const isNsNameEqual = topRequirements.every((topRequirement) => {
187
+ return topRequirement.ns === topRequirements[0].ns && topRequirement.name === topRequirements[0].name
188
+ });
189
+
190
+ if (!isNsNameEqual) {
191
+ console.error("Different names for same dependency is not supported")
192
+ continue
193
+ }
194
+ const topRequirement = topRequirements[0];
195
+ const namespace = topRequirement.ns;
196
+ const name = topRequirement.name;
197
+ const version = dependencyData['version'];
198
+ const purl = new PackageURL(PURL_TYPE, namespace, name, version, undefined, undefined).toString()
199
+
200
+ let requirement = ''
201
+ for (const topRequirement of topRequirements) {
202
+ requirement += topRequirement.constraint + ", "
203
+ }
204
+ if (requirement.endsWith(", ")) {
205
+ requirement = requirement.slice(0, requirement.length-2)
206
+ }
207
+
208
+ results.purls.push({purl: purl, requirement: requirement})
209
+
210
+ }
211
+
212
+
213
+ return results;
214
+
215
+
216
+ }
217
+
218
+
219
+ export function yarnLockV2Parser(fileContent: string, filePath: string): ILocalDependency {
220
+
221
+ const results: ILocalDependency = {file: filePath, purls: []};
222
+
223
+
224
+ return results;
225
+
51
226
  }
@@ -1,28 +1,62 @@
1
- import { FingerprintPacket } from "../WfpProvider/FingerprintPacket";
1
+ import { FingerprintPackage } from '../WfpProvider/FingerprintPackage';
2
+ import FormData from 'form-data';
3
+ import { SbomMode } from '../ScannerTypes';
4
+
2
5
  export class DispatchableItem {
3
- private fingerprintPacket: FingerprintPacket;
6
+ private readonly form: FormData;
4
7
 
5
8
  private errorCounter: number;
6
9
 
7
- constructor(fingerprintPacket: FingerprintPacket) {
8
- this.fingerprintPacket = fingerprintPacket;
10
+ private fingerprintPackage: FingerprintPackage;
11
+
12
+ private engineFlags: number;
13
+
14
+ private sbom: string;
15
+
16
+ private sbomMode: SbomMode;
17
+
18
+ constructor() {
9
19
  this.errorCounter = 0;
20
+ this.form = new FormData();
21
+ }
22
+
23
+ public getForm(): FormData {
24
+ this.form.append('filename', Buffer.from(this.fingerprintPackage.getContent()), 'data.wfp');
25
+ if(this.engineFlags) this.form.append('flags', this.engineFlags);
26
+
27
+ if(this.sbomMode && this.sbom) {
28
+ this.form.append('assets', this.sbom);
29
+ this.form.append('type', this.sbomMode);
30
+ }
31
+
32
+ return this.form;
10
33
  }
11
34
 
12
- increaseErrorCounter() {
35
+ public increaseErrorCounter() {
13
36
  this.errorCounter += 1;
14
37
  }
15
38
 
16
- public getWinnowerResponse(): FingerprintPacket {
17
- return this.fingerprintPacket;
39
+ public getErrorCounter() {
40
+ return this.errorCounter;
18
41
  }
19
42
 
20
- getContent() {
21
- return this.fingerprintPacket.getContent();
43
+ public setFingerprintPackage(fingerprintPackage: FingerprintPackage) {
44
+ this.fingerprintPackage = fingerprintPackage;
22
45
  }
23
46
 
24
- getErrorCounter() {
25
- return this.errorCounter;
47
+ public getFingerprintPackage(): FingerprintPackage {
48
+ return this.fingerprintPackage;
49
+ }
50
+
51
+ public setEngineFlags(engineFlags: number) {
52
+ this.engineFlags = engineFlags;
26
53
  }
27
54
 
55
+ public setSbom(sbom: string, sbomMode: SbomMode) {
56
+ this.sbom = sbom;
57
+ this.sbomMode = sbomMode;
58
+ }
59
+
60
+
61
+
28
62
  }
@@ -11,6 +11,8 @@ import { ScannerCfg } from "../ScannerCfg";
11
11
  import { GlobalControllerAborter } from "./GlobalControllerAborter";
12
12
  import { DispatchableItem } from './DispatchableItem';
13
13
 
14
+ const MAX_CONCURRENT_REQUEST = 30;
15
+
14
16
  export class Dispatcher extends EventEmitter {
15
17
  private scannerCfg: ScannerCfg;
16
18
 
@@ -27,6 +29,9 @@ export class Dispatcher extends EventEmitter {
27
29
  constructor(scannerCfg = new ScannerCfg()) {
28
30
  super();
29
31
  this.scannerCfg = scannerCfg;
32
+ if(this.scannerCfg.CONCURRENCY_LIMIT > MAX_CONCURRENT_REQUEST)
33
+ this.scannerCfg.CONCURRENCY_LIMIT = MAX_CONCURRENT_REQUEST;
34
+
30
35
  this.init();
31
36
  }
32
37
 
@@ -64,8 +69,8 @@ export class Dispatcher extends EventEmitter {
64
69
  this.globalAbortController.abortAll();
65
70
  }
66
71
 
67
- public dispatchItem(disptItem: DispatchableItem): void {
68
- this.pQueue.add(() => this.dispatch(disptItem));
72
+ public dispatchItem(item: DispatchableItem): void {
73
+ this.pQueue.add(() => this.dispatch(item));
69
74
 
70
75
  if (
71
76
  this.pQueue.size + this.pQueue.pending >= this.scannerCfg.DISPATCHER_QUEUE_SIZE_MAX_LIMIT &&
@@ -96,7 +101,6 @@ export class Dispatcher extends EventEmitter {
96
101
  if (this.scannerCfg.ABORT_ON_MAX_RETRIES) this.handleUnrecoverableError(error, disptItem);
97
102
  return;
98
103
  }
99
- // const leftRetry = this.scannerCfg.MAX_RETRIES_FOR_RECOVERABLES_ERRORS - disptItem.getErrorCounter();
100
104
  this.emit(ScannerEvents.DISPATCHER_LOG,`[ SCANNER ]: Recoverable error happened sending WFP content to server. Reason: ${error.code || error.name}`);
101
105
  this.dispatchItem(disptItem);
102
106
  return;
@@ -105,21 +109,14 @@ export class Dispatcher extends EventEmitter {
105
109
  }
106
110
  }
107
111
 
108
- async dispatch(disptItem: DispatchableItem) {
112
+ async dispatch(item: DispatchableItem) {
109
113
  const timeoutController = this.globalAbortController.getAbortController();
110
114
  const timeoutId = setTimeout(() => timeoutController.abort(), this.scannerCfg.TIMEOUT);
111
115
  try {
112
- const form = new FormData();
113
-
114
- form.append('filename', Buffer.from(disptItem.getContent()), 'data.wfp');
115
-
116
- const engineFlag = disptItem.getWinnowerResponse().getEngineFlags();
117
- if(engineFlag) form.append('flags', engineFlag);
118
-
119
116
  this.emit(ScannerEvents.DISPATCHER_WFP_SENDED);
120
117
  const response = await fetch(this.scannerCfg.API_URL, {
121
118
  method: 'post',
122
- body: form,
119
+ body: item.getForm(),
123
120
  headers: { 'User-Agent': this.scannerCfg.CLIENT_TIMESTAMP, 'X-Session': this.scannerCfg.API_KEY },
124
121
  signal: timeoutController.signal,
125
122
  });
@@ -138,13 +135,13 @@ export class Dispatcher extends EventEmitter {
138
135
  const dataAsText = await response.text();
139
136
  const dataAsObj = JSON.parse(dataAsText);
140
137
 
141
- const dispatcherResponse = new DispatcherResponse(dataAsObj, disptItem.getContent());
138
+ const dispatcherResponse = new DispatcherResponse(dataAsObj, item.getFingerprintPackage().getContent());
142
139
  this.emit(ScannerEvents.DISPATCHER_NEW_DATA, dispatcherResponse);
143
140
  return Promise.resolve();
144
141
  } catch (e) {
145
142
  clearTimeout(timeoutId);
146
143
  this.globalAbortController.removeAbortController(timeoutController);
147
- this.errorHandler(e, disptItem);
144
+ this.errorHandler(e, item);
148
145
  return Promise.resolve();
149
146
  }
150
147
  }
@@ -15,15 +15,13 @@ import { ScannerEvents, ScannerInput } from './ScannerTypes';
15
15
  import sortPaths from 'sort-paths';
16
16
 
17
17
  import { WfpProvider } from './WfpProvider/WfpProvider';
18
- import { FingerprintPacket } from './WfpProvider/FingerprintPacket';
18
+ import { FingerprintPackage } from './WfpProvider/FingerprintPackage';
19
19
  import { WfpCalculator } from './WfpProvider/WfpCalculator/WfpCalculator';
20
20
  import { WfpSplitter } from './WfpProvider/WfpSplitter/WfpSplitter';
21
21
 
22
22
  let finishPromiseResolve;
23
23
  let finishPromiseReject;
24
24
 
25
-
26
-
27
25
  export class Scanner extends EventEmitter {
28
26
  private scannerCfg: ScannerCfg;
29
27
 
@@ -88,12 +86,18 @@ export class Scanner extends EventEmitter {
88
86
  }
89
87
 
90
88
  setWinnowerListeners() {
91
- this.wfpProvider.on(ScannerEvents.WINNOWING_NEW_CONTENT, (fingerprintPacket: FingerprintPacket) => {
92
- this.emit(ScannerEvents.WINNOWING_NEW_CONTENT, fingerprintPacket);
89
+ this.wfpProvider.on(ScannerEvents.WINNOWING_NEW_CONTENT, (fingerprintPackage: FingerprintPackage) => {
90
+ this.emit(ScannerEvents.WINNOWING_NEW_CONTENT, fingerprintPackage);
93
91
  this.reportLog(`[ SCANNER ]: New WFP content`);
94
- fingerprintPacket.setEngineFlags(this.scannerInput[0].engineFlags);
95
- const disptItem = new DispatchableItem(fingerprintPacket);
96
- this.dispatcher.dispatchItem(disptItem);
92
+
93
+ const item = new DispatchableItem();
94
+ item.setFingerprintPackage(fingerprintPackage);
95
+ if(this.scannerInput[0]?.engineFlags) item.setEngineFlags(this.scannerInput[0]?.engineFlags);
96
+
97
+ if(this.scannerInput[0]?.sbom && this.scannerInput[0]?.sbomMode)
98
+ item.setSbom(this.scannerInput[0]?.sbom, this.scannerInput[0]?.sbomMode);
99
+
100
+ this.dispatcher.dispatchItem(item);
97
101
  });
98
102
 
99
103
  this.wfpProvider.on(ScannerEvents.WINNOWER_LOG, (msg) => {
@@ -116,7 +120,7 @@ export class Scanner extends EventEmitter {
116
120
  this.wfpProvider.resume();
117
121
  });
118
122
 
119
- this.dispatcher.on(ScannerEvents.DISPATCHER_NEW_DATA, async (response) => {
123
+ this.dispatcher.on(ScannerEvents.DISPATCHER_NEW_DATA, async (response: DispatcherResponse) => {
120
124
  this.processingNewData = true;
121
125
  this.processedFiles += response.getNumberOfFilesScanned();
122
126
  this.reportLog(`[ SCANNER ]: Received results of ${response.getNumberOfFilesScanned()} files`);
@@ -134,8 +138,8 @@ export class Scanner extends EventEmitter {
134
138
  }
135
139
  });
136
140
 
137
- this.dispatcher.on(ScannerEvents.DISPATCHER_ITEM_NO_DISPATCHED, (disptItem) => {
138
- const filesNotScanned = disptItem.getWinnowerResponse().getFilesWinnowed();
141
+ this.dispatcher.on(ScannerEvents.DISPATCHER_ITEM_NO_DISPATCHED, (disptItem: DispatchableItem) => {
142
+ const filesNotScanned = disptItem.getFingerprintPackage().getFilesFingerprinted();
139
143
  this.appendFilesToNotScanned(filesNotScanned);
140
144
  });
141
145
 
@@ -143,8 +147,8 @@ export class Scanner extends EventEmitter {
143
147
  this.reportLog(msg);
144
148
  });
145
149
 
146
- this.dispatcher.on(ScannerEvents.ERROR, (error, disptItem) => {
147
- const wfpContent = disptItem.getWinnowerResponse().getContent();
150
+ this.dispatcher.on(ScannerEvents.ERROR, (error: Error, disptItem: DispatchableItem) => {
151
+ const wfpContent = disptItem.getFingerprintPackage().getContent();
148
152
  fs.writeFileSync(`${this.workDirectory}/failed.wfp`, wfpContent, 'utf8');
149
153
  this.errorHandler(error, ScannerEvents.MODULE_DISPATCHER);
150
154
  });
@@ -20,10 +20,11 @@ export class ScannerCfg {
20
20
 
21
21
  ABORT_ON_MAX_RETRIES = true;
22
22
 
23
- // Persist results after [ X ] number of server responses.
23
+ // Persist results after [ X ] server responses
24
24
  MAX_RESPONSES_IN_BUFFER = 300;
25
25
 
26
26
  DISPATCHER_QUEUE_SIZE_MAX_LIMIT = 300;
27
27
 
28
28
  DISPATCHER_QUEUE_SIZE_MIN_LIMIT = 200;
29
+
29
30
  };
@@ -30,13 +30,21 @@ export enum ScannerEvents {
30
30
 
31
31
  export enum WinnowingMode {
32
32
  FULL_WINNOWING = 'FULL_WINNOWING',
33
+ FULL_WINNOWING_HPSM = 'FULL_WINNOWING_HPSM',
33
34
  WINNOWING_ONLY_MD5 = 'WINNOWING_ONLY_MD5',
34
35
  };
35
36
 
37
+ export enum SbomMode {
38
+ SBOM_IGNORE = 'blacklist',
39
+ SBOM_IDENTIFY = 'identify'
40
+ }
41
+
36
42
  export interface ScannerInput {
37
- engineFlags?: number;
38
- folderRoot?: string;
39
43
  fileList: Array<string>;
44
+ folderRoot?: string;
45
+ engineFlags?: number;
40
46
  winnowingMode?: WinnowingMode; // Enable winnowing algorithm, otherwise is scanned only MD5
41
47
  wfpPath?: string;
48
+ sbom?: string;
49
+ sbomMode?: SbomMode;
42
50
  };
@@ -1,8 +1,6 @@
1
- export class FingerprintPacket {
1
+ export class FingerprintPackage {
2
2
  private wfpContent: string;
3
3
 
4
- private engineFlags: number;
5
-
6
4
  private scanRoot: string;
7
5
 
8
6
  constructor(wfpContent: string, scanRoot = '') {
@@ -10,22 +8,14 @@ export class FingerprintPacket {
10
8
  this.scanRoot = scanRoot;
11
9
  }
12
10
 
13
- public isEqual(fingerprintPacket: FingerprintPacket): boolean {
14
- return this.getContent() === fingerprintPacket.getContent();
11
+ public isEqual(fingerprintPackage: FingerprintPackage): boolean {
12
+ return this.getContent() === fingerprintPackage.getContent();
15
13
  }
16
14
 
17
- public getContent() {
15
+ public getContent(): string {
18
16
  return this.wfpContent;
19
17
  }
20
18
 
21
- public setEngineFlags(engineFlags: number): void {
22
- this.engineFlags = engineFlags;
23
- }
24
-
25
- public getEngineFlags(): number {
26
- return this.engineFlags;
27
- }
28
-
29
19
  public getNumberFilesFingerprinted() {
30
20
  const match = this.getContent().match(/file=/g);
31
21
  if(!match) return 0;