scanoss 0.2.28 → 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 (128) 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/workspace.xml +296 -6
  5. package/.nyc_output/a25d3ac4-ee71-4c5e-926e-3a17714555cd.json +1 -0
  6. package/.nyc_output/processinfo/a25d3ac4-ee71-4c5e-926e-3a17714555cd.json +1 -0
  7. package/.nyc_output/processinfo/index.json +1 -0
  8. package/.reuse/dep5 +16 -0
  9. package/LICENSES/CC0-1.0.txt +121 -0
  10. package/LICENSES/MIT.txt +9 -0
  11. package/README.md +9 -0
  12. package/build/main/bin/cli-bin.js +4 -3
  13. package/build/main/commands/dep.js +1 -2
  14. package/build/main/commands/fingerprint.js +17 -9
  15. package/build/main/commands/helpers.js +1 -2
  16. package/build/main/commands/scan.js +3 -2
  17. package/build/main/index.js +1 -2
  18. package/build/main/lib/dependencies/DependencyScanner.d.ts +1 -1
  19. package/build/main/lib/dependencies/DependencyScanner.js +23 -12
  20. package/build/main/lib/dependencies/DependencyScannerCfg.js +1 -2
  21. package/build/main/lib/dependencies/DependencyTypes.js +0 -1
  22. package/build/main/lib/dependencies/LocalDependency/DependencyTypes.js +0 -1
  23. package/build/main/lib/dependencies/LocalDependency/LocalDependency.js +3 -2
  24. package/build/main/lib/dependencies/LocalDependency/parsers/golangParser.d.ts +1 -0
  25. package/build/main/lib/dependencies/LocalDependency/parsers/golangParser.js +50 -16
  26. package/build/main/lib/dependencies/LocalDependency/parsers/mavenParser.js +1 -2
  27. package/build/main/lib/dependencies/LocalDependency/parsers/npmParser.d.ts +10 -0
  28. package/build/main/lib/dependencies/LocalDependency/parsers/npmParser.js +146 -10
  29. package/build/main/lib/dependencies/LocalDependency/parsers/pyParser.js +1 -2
  30. package/build/main/lib/dependencies/LocalDependency/parsers/rubyParser.js +1 -2
  31. package/build/main/lib/dependencies/LocalDependency/parsers/utils.js +1 -2
  32. package/build/main/lib/filters/defaultFilter.js +1 -2
  33. package/build/main/lib/filters/filtering.js +1 -2
  34. package/build/main/lib/grpc/GrpcDependencyService.js +1 -2
  35. package/build/main/lib/grpc/scanoss/api/components/v2/scanoss-components_grpc_pb.d.ts +62 -0
  36. package/build/main/lib/grpc/scanoss/api/components/v2/scanoss-components_grpc_pb.js +128 -0
  37. package/build/main/lib/grpc/scanoss/api/components/v2/scanoss-components_pb.d.ts +1 -0
  38. package/build/main/lib/grpc/scanoss/api/components/v2/scanoss-components_pb.js +1403 -0
  39. package/build/main/lib/scanner/Dispatcher/DispatchableItem.js +1 -2
  40. package/build/main/lib/scanner/Dispatcher/Dispatcher.js +1 -2
  41. package/build/main/lib/scanner/Dispatcher/DispatcherResponse.js +1 -2
  42. package/build/main/lib/scanner/Dispatcher/GlobalControllerAborter.js +1 -2
  43. package/build/main/lib/scanner/Scannable/ScannableItem.js +1 -2
  44. package/build/main/lib/scanner/Scanner.js +1 -2
  45. package/build/main/lib/scanner/ScannerCfg.js +2 -3
  46. package/build/main/lib/scanner/ScannerTypes.d.ts +1 -0
  47. package/build/main/lib/scanner/ScannerTypes.js +2 -2
  48. package/build/main/lib/scanner/WfpProvider/FingerprintPackage.js +1 -2
  49. package/build/main/lib/scanner/WfpProvider/WfpCalculator/WfpCalculator.js +175 -18
  50. package/build/main/lib/scanner/WfpProvider/WfpCalculator/Winnower.d.ts +3 -0
  51. package/build/main/lib/scanner/WfpProvider/WfpCalculator/Winnower.js +211 -0
  52. package/build/main/lib/scanner/WfpProvider/WfpProvider.js +1 -2
  53. package/build/main/lib/scanner/WfpProvider/WfpSplitter/WfpSplitter.js +1 -2
  54. package/build/main/lib/tree/File.js +1 -2
  55. package/build/main/lib/tree/Folder.js +1 -2
  56. package/build/main/lib/tree/Node.js +1 -2
  57. package/build/main/lib/tree/Tree.js +1 -2
  58. package/build/module/bin/cli-bin.js +4 -2
  59. package/build/module/commands/fingerprint.js +22 -13
  60. package/build/module/commands/scan.js +4 -2
  61. package/build/module/lib/dependencies/DependencyScanner.d.ts +1 -1
  62. package/build/module/lib/dependencies/DependencyScanner.js +23 -11
  63. package/build/module/lib/dependencies/LocalDependency/LocalDependency.js +5 -3
  64. package/build/module/lib/dependencies/LocalDependency/parsers/golangParser.d.ts +1 -0
  65. package/build/module/lib/dependencies/LocalDependency/parsers/golangParser.js +47 -14
  66. package/build/module/lib/dependencies/LocalDependency/parsers/npmParser.d.ts +10 -0
  67. package/build/module/lib/dependencies/LocalDependency/parsers/npmParser.js +140 -8
  68. package/build/module/lib/grpc/scanoss/api/components/v2/scanoss-components_grpc_pb.d.ts +62 -0
  69. package/build/module/lib/grpc/scanoss/api/components/v2/scanoss-components_grpc_pb.js +128 -0
  70. package/build/module/lib/grpc/scanoss/api/components/v2/scanoss-components_pb.d.ts +1 -0
  71. package/build/module/lib/grpc/scanoss/api/components/v2/scanoss-components_pb.js +1403 -0
  72. package/build/module/lib/scanner/ScannerCfg.js +2 -2
  73. package/build/module/lib/scanner/ScannerTypes.d.ts +1 -0
  74. package/build/module/lib/scanner/ScannerTypes.js +2 -1
  75. package/build/module/lib/scanner/WfpProvider/WfpCalculator/WfpCalculator.js +175 -17
  76. package/build/module/lib/scanner/WfpProvider/WfpCalculator/Winnower.d.ts +3 -0
  77. package/build/module/lib/scanner/WfpProvider/WfpCalculator/Winnower.js +211 -0
  78. package/build/tsconfig.module.tsbuildinfo +1 -1
  79. package/build/tsconfig.tsbuildinfo +1 -1
  80. package/package.json +6 -17
  81. package/src/bin/cli-bin.ts +3 -1
  82. package/src/commands/fingerprint.ts +23 -14
  83. package/src/commands/scan.ts +10 -2
  84. package/src/lib/dependencies/DependencyScanner.ts +20 -12
  85. package/src/lib/dependencies/LocalDependency/LocalDependency.ts +8 -2
  86. package/src/lib/dependencies/LocalDependency/parsers/golangParser.ts +67 -15
  87. package/src/lib/dependencies/LocalDependency/parsers/npmParser.ts +182 -7
  88. package/src/lib/scanner/ScannerCfg.ts +2 -1
  89. package/src/lib/scanner/ScannerTypes.ts +1 -0
  90. package/src/lib/scanner/WfpProvider/FingerprintPackage.ts +1 -1
  91. package/src/lib/scanner/WfpProvider/WfpCalculator/WfpCalculator.ts +174 -17
  92. package/tests/WfpCalculator.spec.ts +103 -0
  93. package/{test/dependencies/data → tests/data/dependencies}/Gemfile/1/Gemfile +0 -0
  94. package/{test/dependencies/data → tests/data/dependencies}/Gemfile/1/Gemfile~ +0 -0
  95. package/{test/dependencies/data → tests/data/dependencies}/Gemfile/2/Gemfile +0 -0
  96. package/{test/dependencies/data → tests/data/dependencies}/Gemfile/2/Gemfile~ +0 -0
  97. package/{test/dependencies/data → tests/data/dependencies}/Gemfile/3/Gemfile +0 -0
  98. package/{test/dependencies/data → tests/data/dependencies}/Gemfile/3/Gemfile~ +0 -0
  99. package/{test/dependencies/data → tests/data/dependencies}/Gemfile/4/Gemfile +0 -0
  100. package/{test/dependencies/data → tests/data/dependencies}/Gemfile/4/Gemfile~ +0 -0
  101. package/{test/dependencies/data → tests/data/dependencies}/Gemfile.lock/1/Gemfile.lock +0 -0
  102. package/{test/dependencies/data → tests/data/dependencies}/Gemfile.lock/2/Gemfile.lock +0 -0
  103. package/{test/dependencies/data → tests/data/dependencies}/Gemfile.lock/2/Gemfile.lock~ +0 -0
  104. package/tests/data/dependencies/go.sum/1/go.sum +119 -0
  105. package/tests/data/dependencies/go.sum/depJSON.sh +23 -0
  106. package/tests/data/dependencies/package-lock/1/package-lock.json +715 -0
  107. package/tests/data/dependencies/package-lock/2/package-lock.json +32069 -0
  108. package/tests/data/dependencies/package-lock/3/package-lock.json +9013 -0
  109. package/{test/dependencies/data → tests/data/dependencies}/pom.xml/1/pom.xml +0 -0
  110. package/tests/data/dependencies/yarn-lock/generate_expected_output.sh +4 -0
  111. package/tests/data/dependencies/yarn-lock/v1/yarn.lock +50 -0
  112. package/tests/data/dependencies/yarn-lock/v1/yarn.lock-expected +13 -0
  113. package/tests/data/dependencies/yarn-lock/v1-complex/yarn.lock +27 -0
  114. package/tests/data/dependencies/yarn-lock/v1-complex/yarn.lock-expected +8 -0
  115. package/tests/data/dependencies/yarn-lock/v1-complex2/yarn.lock +220 -0
  116. package/tests/data/dependencies/yarn-lock/v2/yarn.lock +31 -0
  117. package/tests/data/dependencies/yarn-lock/v2/yarn.lock-expected +57 -0
  118. package/tests/data/dependencies/yarn-lock/v2-local/yarn.lock +11 -0
  119. package/tests/data/dependencies/yarn-lock/v2-local/yarn.lock-expected +27204 -0
  120. package/tests/data/scanner/file1.c +41 -0
  121. package/tests/data/scanner/file2.go +87 -0
  122. package/tests/dependencies/golangParser.goModParser.specs.ts +146 -0
  123. package/tests/dependencies/npmParser.spec.ts +133 -0
  124. package/tsconfig.json +4 -3
  125. package/yarn.lock +4596 -5321
  126. package/examples/defaultFilter.json +0 -203
  127. package/package-lock.json +0 -18588
  128. package/src/lib/scanner/Winnower/WinnowerExtractor.ts +0 -37
@@ -1,11 +1,14 @@
1
- import { isFolder } from "./helpers";
2
- import { ScannerEvents, WfpCalculator } from "..";
3
- import { Tree } from "../lib/tree/Tree";
4
- import { FilterList } from "../lib/filters/filtering";
5
- import { FingerprintPackage } from "../lib/scanner/WfpProvider/FingerprintPackage";
1
+ import { isFolder } from './helpers';
2
+ import { ScannerEvents, WfpCalculator, WinnowingMode } from '..';
3
+ import { Tree } from '../lib/tree/Tree';
4
+ import { FilterList } from '../lib/filters/filtering';
5
+ import {
6
+ FingerprintPackage
7
+ } from '../lib/scanner/WfpProvider/FingerprintPackage';
6
8
  import fs from 'fs';
7
- import { defaultFilter } from "../lib/filters/defaultFilter";
9
+ import { defaultFilter } from '../lib/filters/defaultFilter';
8
10
  import cliProgress from 'cli-progress';
11
+ import { IWfpProviderInput } from '../lib/scanner/WfpProvider/WfpProvider';
9
12
 
10
13
 
11
14
  export async function fingerprintHandler(rootPath: string, options: any): Promise<void> {
@@ -15,14 +18,19 @@ export async function fingerprintHandler(rootPath: string, options: any): Promis
15
18
  const pathIsFolder = await isFolder(rootPath);
16
19
  const wfpCalculator = new WfpCalculator();
17
20
 
18
- const tree = new Tree(rootPath);
19
- const filter = new FilterList('');
20
- filter.load(defaultFilter as FilterList);
21
+ let filesToFingerprint: string[] = [];
22
+ if (pathIsFolder) {
23
+ const tree = new Tree(rootPath);
24
+ const filter = new FilterList('');
25
+ filter.load(defaultFilter as FilterList);
21
26
 
22
- tree.loadFilter(filter);
23
- tree.buildTree();
27
+ tree.loadFilter(filter);
28
+ tree.buildTree();
29
+ filesToFingerprint = tree.getFileList();
30
+ } else {
31
+ filesToFingerprint.push(rootPath)
32
+ }
24
33
 
25
- const filesToFingerprint = tree.getFileList();
26
34
 
27
35
  const optBar1 = { format: 'Fingerprinting Progress: [{bar}] {percentage}% | Fingerprinted {value} files of {total}' };
28
36
  const bar1 = new cliProgress.SingleBar(optBar1, cliProgress.Presets.shades_classic);
@@ -48,8 +56,9 @@ export async function fingerprintHandler(rootPath: string, options: any): Promis
48
56
  }
49
57
  });
50
58
 
51
-
52
- wfpCalculator.start({fileList: filesToFingerprint, folderRoot: rootPath});
59
+ const wfpInput: IWfpProviderInput = {fileList: filesToFingerprint, folderRoot: rootPath}
60
+ if(options.hpsm) wfpInput.winnowingMode = WinnowingMode.FULL_WINNOWING_HPSM;
61
+ wfpCalculator.start(wfpInput);
53
62
 
54
63
 
55
64
  }
@@ -1,10 +1,17 @@
1
1
  import { Scanner } from '../lib/scanner/Scanner';
2
- import { SbomMode, ScannerEvents, ScannerInput } from '../lib/scanner/ScannerTypes';
2
+ import {
3
+ SbomMode,
4
+ ScannerEvents,
5
+ ScannerInput,
6
+ WinnowingMode
7
+ } from '../lib/scanner/ScannerTypes';
3
8
  import { ScannerCfg } from '../lib/scanner/ScannerCfg';
4
9
  import { Tree } from '../lib/tree/Tree';
5
10
 
6
11
  import cliProgress from 'cli-progress';
7
- import { DispatcherResponse } from '../lib/scanner/Dispatcher/DispatcherResponse';
12
+ import {
13
+ DispatcherResponse
14
+ } from '../lib/scanner/Dispatcher/DispatcherResponse';
8
15
  import { defaultFilter } from '../lib/filters/defaultFilter';
9
16
  import { FilterList } from '../lib/filters/filtering';
10
17
 
@@ -80,6 +87,7 @@ export async function scanHandler(rootPath: string, options: any): Promise<void>
80
87
  });
81
88
 
82
89
  if (options.wfp) scannerInput.wfpPath = rootPath;
90
+ if (options.hpsm) scannerInput.winnowingMode = WinnowingMode.FULL_WINNOWING_HPSM
83
91
 
84
92
  if (options.ignore) {
85
93
  scannerInput.sbom = fs.readFileSync(options.ignore, 'utf-8');
@@ -26,9 +26,10 @@ export class DependencyScanner {
26
26
  const grpcResponse = await this.grpcDependencyService.get(request);
27
27
  const response = grpcResponse.toObject();
28
28
 
29
-
30
29
  // Extract scope from localDependencies and add it to response
31
- this.mergeScopeField(localDependencies, response);
30
+ // Also adds the requirements field from localDependency to the response if the server didn't
31
+ // replay back a version
32
+ this.repairOutput(localDependencies, response);
32
33
  return response;
33
34
  }
34
35
 
@@ -71,27 +72,34 @@ export class DependencyScanner {
71
72
  }
72
73
  }
73
74
 
74
- private mergeScopeField(localdependency: ILocalDependencies, serverResponse: DependencyResponse.AsObject
75
- ): IDependencyResponse {
76
-
77
- const scopeHashMap = {};
75
+ private repairOutput(localdependency: ILocalDependencies, serverResponse: DependencyResponse.AsObject) {
78
76
 
77
+ // Create a map with key = [filename + purl] and the value is an object containing:
78
+ // * The scope of the local dependency
79
+ // * The requirement of the local dependency
80
+ // Later this map is used to add information in the server response
81
+ const localDependencyInfo = {};
79
82
  for (const file of localdependency.files) {
80
83
  const filename = file.file
81
- for (const dependency of file.purls) {
82
- if (dependency?.scope) scopeHashMap[filename + dependency.purl] = dependency.scope;
84
+ for (const localDependency of file.purls) {
85
+ const localInfo = {}
86
+ if (localDependency?.scope) localInfo['scope'] = localDependency.scope
87
+ if(localDependency?.requirement) localInfo['requirement'] = localDependency.requirement
88
+ localDependencyInfo[filename + localDependency.purl] = localInfo;
83
89
  }
84
90
  }
85
91
 
86
92
  for (const file of serverResponse.filesList) {
87
93
  const filename = file.file
88
94
  for (const dependency of file.dependenciesList) {
89
- const scope = scopeHashMap[filename + dependency.purl];
90
- if (scope) dependency['scope'] = scope;
95
+ const localDependencyData = localDependencyInfo[filename + dependency.purl];
96
+ if (localDependencyData?.scope) dependency['scope'] = localDependencyData.scope;
97
+ if (localDependencyData?.requirement && dependency.version == "") {
98
+ dependency.version = localDependencyData.requirement;
99
+ }
91
100
  }
92
101
  }
93
-
94
- return serverResponse;
95
102
  }
96
103
 
104
+
97
105
  }
@@ -3,9 +3,13 @@ import fs from 'fs';
3
3
  import { ParserFuncType, ILocalDependencies } from "./DependencyTypes";
4
4
  import { requirementsParser } from "./parsers/pyParser";
5
5
  import { pomParser } from "./parsers/mavenParser";
6
- import { packagelockParser, packageParser } from "./parsers/npmParser";
6
+ import {
7
+ packagelockParser,
8
+ packageParser,
9
+ yarnLockParser
10
+ } from './parsers/npmParser';
7
11
  import { gemfilelockParser, gemfileParser } from "./parsers/rubyParser";
8
- import { goModParser } from './parsers/golangParser';
12
+ import { goModParser, goSumParser } from './parsers/golangParser';
9
13
 
10
14
  export class LocalDependencies {
11
15
 
@@ -24,6 +28,8 @@ export class LocalDependencies {
24
28
  'Gemfile': gemfileParser,
25
29
  'Gemfile.lock': gemfilelockParser,
26
30
  'go.mod': goModParser,
31
+ 'go.sum': goSumParser,
32
+ 'yarn.lock': yarnLockParser
27
33
  };
28
34
  }
29
35
 
@@ -3,15 +3,6 @@ import { ILocalDependency } from "../DependencyTypes";
3
3
  import { PackageURL } from "packageurl-js";
4
4
  import path from "path";
5
5
 
6
- function parseModule (str: string) {
7
- const res = /(?<type>[^\s]+)(?:\s)+(?<ns_name>[^\s]+)\s?(?<version>(.*))/.exec(str);
8
- return {
9
- type: res.groups.type,
10
- ns_name: res.groups.ns_name,
11
- version: res.groups.version
12
- };
13
- }
14
-
15
6
  function parseDepLink (str: string) {
16
7
  const res = /.*?(?<ns_name>[^\s]+)\s+(?<version>(.*))/.exec(str);
17
8
  return {
@@ -20,6 +11,16 @@ function parseDepLink (str: string) {
20
11
  };
21
12
  }
22
13
 
14
+ function getDepDataGoModFromLine(line: string) {
15
+ const {ns_name, version} = parseDepLink(line);
16
+
17
+ const index = ns_name.lastIndexOf('/');
18
+ const namespace = ns_name.substring(0, index);
19
+ const name = ns_name.substring(index + 1);
20
+
21
+ return {namespace, name, version}
22
+ }
23
+
23
24
  // Removes comments and spaces
24
25
  function preprocessLine(line: string) {
25
26
  if (line.includes("//"))
@@ -45,7 +46,6 @@ export function goModParser(fileContent: string, filePath: string): ILocalDepend
45
46
  const lines = fileContent.split('\n');
46
47
 
47
48
  const require = [];
48
- const exclude = [];
49
49
 
50
50
  for (let num = 0 ; num < lines.length ; num+=1) {
51
51
 
@@ -57,11 +57,7 @@ export function goModParser(fileContent: string, filePath: string): ILocalDepend
57
57
  line = preprocessLine(lines[num]);
58
58
  while (num < lines.length && line!==')') {
59
59
 
60
- const {ns_name, version} = parseDepLink(line);
61
-
62
- const index = ns_name.lastIndexOf('/');
63
- const namespace = ns_name.substring(0, index);
64
- const name = ns_name.substring(index + 1);
60
+ const {namespace, name, version} = getDepDataGoModFromLine(line)
65
61
 
66
62
  const purlString = new PackageURL(PURL_TYPE, namespace, name, version, undefined, undefined).toString();
67
63
  results.purls.push({purl: purlString});
@@ -76,3 +72,59 @@ export function goModParser(fileContent: string, filePath: string): ILocalDepend
76
72
 
77
73
  return results;
78
74
  }
75
+
76
+
77
+
78
+
79
+
80
+ function parseGoSumDepLink (str: string) {
81
+ const res = /.*?(?<ns_name>[^\s]+)\s+(?<version>(.*))\s+h1:(?<checksum>(.*))/.exec(str);
82
+ return {
83
+ ns_name: res?.groups?.ns_name,
84
+ version: res?.groups?.version,
85
+ checksum: res?.groups?.checksum
86
+ };
87
+ }
88
+
89
+ function getDepDataGoSumFromLine(line: string) {
90
+ const {ns_name, version} = parseGoSumDepLink(line);
91
+
92
+ if (!ns_name) return {};
93
+
94
+ const index = ns_name.lastIndexOf('/');
95
+ const namespace = ns_name.substring(0, index);
96
+ const name = ns_name.substring(index + 1);
97
+
98
+ return {namespace, name, version}
99
+ }
100
+
101
+ // See reference on: https://go.dev/ref/mod#go-mod-file
102
+ export function goSumParser(fileContent: string, filePath: string): ILocalDependency {
103
+
104
+ // If the file is not a go.mod manifest file, return an empty results
105
+ const results: ILocalDependency = { file: filePath, purls: [] };
106
+ if (path.basename(filePath) != 'go.sum')
107
+ return results;
108
+
109
+
110
+ const lines = fileContent.split('\n');
111
+ for (let num = 0; num < lines.length; num += 1) {
112
+
113
+ let line = preprocessLine(lines[num]); //Deletes coments
114
+ if(!line) continue
115
+
116
+ line = line.replace('/go.mod', '')
117
+ const {namespace, name, version} = getDepDataGoSumFromLine(line)
118
+
119
+ if (!name) continue
120
+
121
+ //const purlString = new PackageURL(PURL_TYPE, namespace, name, undefined, undefined, undefined).toString();
122
+ const purlString = `pkg:${PURL_TYPE}/${namespace}/${name}`
123
+ results.purls.push({purl: purlString, requirement: version})
124
+ }
125
+
126
+ return results;
127
+
128
+
129
+ }
130
+
@@ -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
  }
@@ -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,6 +30,7 @@ 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
 
@@ -12,7 +12,7 @@ export class FingerprintPackage {
12
12
  return this.getContent() === fingerprintPackage.getContent();
13
13
  }
14
14
 
15
- public getContent() {
15
+ public getContent(): string {
16
16
  return this.wfpContent;
17
17
  }
18
18