scanoss 1.27.1__tar.gz → 1.28.0__tar.gz

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 (100) hide show
  1. {scanoss-1.27.1/src/scanoss.egg-info → scanoss-1.28.0}/PKG-INFO +1 -1
  2. {scanoss-1.27.1 → scanoss-1.28.0}/src/scanoss/__init__.py +1 -1
  3. {scanoss-1.27.1 → scanoss-1.28.0}/src/scanoss/cyclonedx.py +81 -0
  4. scanoss-1.28.0/src/scanoss/data/build_date.txt +1 -0
  5. {scanoss-1.27.1 → scanoss-1.28.0}/src/scanoss/scanners/scanner_hfh.py +9 -0
  6. {scanoss-1.27.1 → scanoss-1.28.0}/src/scanoss/scanossgrpc.py +1 -1
  7. {scanoss-1.27.1 → scanoss-1.28.0/src/scanoss.egg-info}/PKG-INFO +1 -1
  8. scanoss-1.27.1/src/scanoss/data/build_date.txt +0 -1
  9. {scanoss-1.27.1 → scanoss-1.28.0}/LICENSE +0 -0
  10. {scanoss-1.27.1 → scanoss-1.28.0}/PACKAGE.md +0 -0
  11. {scanoss-1.27.1 → scanoss-1.28.0}/README.md +0 -0
  12. {scanoss-1.27.1 → scanoss-1.28.0}/pyproject.toml +0 -0
  13. {scanoss-1.27.1 → scanoss-1.28.0}/setup.cfg +0 -0
  14. {scanoss-1.27.1 → scanoss-1.28.0}/src/protoc_gen_swagger/__init__.py +0 -0
  15. {scanoss-1.27.1 → scanoss-1.28.0}/src/protoc_gen_swagger/options/__init__.py +0 -0
  16. {scanoss-1.27.1 → scanoss-1.28.0}/src/protoc_gen_swagger/options/annotations_pb2.py +0 -0
  17. {scanoss-1.27.1 → scanoss-1.28.0}/src/protoc_gen_swagger/options/annotations_pb2_grpc.py +0 -0
  18. {scanoss-1.27.1 → scanoss-1.28.0}/src/protoc_gen_swagger/options/openapiv2_pb2.py +0 -0
  19. {scanoss-1.27.1 → scanoss-1.28.0}/src/protoc_gen_swagger/options/openapiv2_pb2_grpc.py +0 -0
  20. {scanoss-1.27.1 → scanoss-1.28.0}/src/scanoss/api/__init__.py +0 -0
  21. {scanoss-1.27.1 → scanoss-1.28.0}/src/scanoss/api/common/__init__.py +0 -0
  22. {scanoss-1.27.1 → scanoss-1.28.0}/src/scanoss/api/common/v2/__init__.py +0 -0
  23. {scanoss-1.27.1 → scanoss-1.28.0}/src/scanoss/api/common/v2/scanoss_common_pb2.py +0 -0
  24. {scanoss-1.27.1 → scanoss-1.28.0}/src/scanoss/api/common/v2/scanoss_common_pb2_grpc.py +0 -0
  25. {scanoss-1.27.1 → scanoss-1.28.0}/src/scanoss/api/components/__init__.py +0 -0
  26. {scanoss-1.27.1 → scanoss-1.28.0}/src/scanoss/api/components/v2/__init__.py +0 -0
  27. {scanoss-1.27.1 → scanoss-1.28.0}/src/scanoss/api/components/v2/scanoss_components_pb2.py +0 -0
  28. {scanoss-1.27.1 → scanoss-1.28.0}/src/scanoss/api/components/v2/scanoss_components_pb2_grpc.py +0 -0
  29. {scanoss-1.27.1 → scanoss-1.28.0}/src/scanoss/api/cryptography/v2/scanoss_cryptography_pb2.py +0 -0
  30. {scanoss-1.27.1 → scanoss-1.28.0}/src/scanoss/api/cryptography/v2/scanoss_cryptography_pb2_grpc.py +0 -0
  31. {scanoss-1.27.1 → scanoss-1.28.0}/src/scanoss/api/dependencies/__init__.py +0 -0
  32. {scanoss-1.27.1 → scanoss-1.28.0}/src/scanoss/api/dependencies/v2/__init__.py +0 -0
  33. {scanoss-1.27.1 → scanoss-1.28.0}/src/scanoss/api/dependencies/v2/scanoss_dependencies_pb2.py +0 -0
  34. {scanoss-1.27.1 → scanoss-1.28.0}/src/scanoss/api/dependencies/v2/scanoss_dependencies_pb2_grpc.py +0 -0
  35. {scanoss-1.27.1 → scanoss-1.28.0}/src/scanoss/api/geoprovenance/__init__.py +0 -0
  36. {scanoss-1.27.1 → scanoss-1.28.0}/src/scanoss/api/geoprovenance/v2/__init__.py +0 -0
  37. {scanoss-1.27.1 → scanoss-1.28.0}/src/scanoss/api/geoprovenance/v2/scanoss_geoprovenance_pb2.py +0 -0
  38. {scanoss-1.27.1 → scanoss-1.28.0}/src/scanoss/api/geoprovenance/v2/scanoss_geoprovenance_pb2_grpc.py +0 -0
  39. {scanoss-1.27.1 → scanoss-1.28.0}/src/scanoss/api/scanning/__init__.py +0 -0
  40. {scanoss-1.27.1 → scanoss-1.28.0}/src/scanoss/api/scanning/v2/__init__.py +0 -0
  41. {scanoss-1.27.1 → scanoss-1.28.0}/src/scanoss/api/scanning/v2/scanoss_scanning_pb2.py +0 -0
  42. {scanoss-1.27.1 → scanoss-1.28.0}/src/scanoss/api/scanning/v2/scanoss_scanning_pb2_grpc.py +0 -0
  43. {scanoss-1.27.1 → scanoss-1.28.0}/src/scanoss/api/semgrep/__init__.py +0 -0
  44. {scanoss-1.27.1 → scanoss-1.28.0}/src/scanoss/api/semgrep/v2/__init__.py +0 -0
  45. {scanoss-1.27.1 → scanoss-1.28.0}/src/scanoss/api/semgrep/v2/scanoss_semgrep_pb2.py +0 -0
  46. {scanoss-1.27.1 → scanoss-1.28.0}/src/scanoss/api/semgrep/v2/scanoss_semgrep_pb2_grpc.py +0 -0
  47. {scanoss-1.27.1 → scanoss-1.28.0}/src/scanoss/api/vulnerabilities/__init__.py +0 -0
  48. {scanoss-1.27.1 → scanoss-1.28.0}/src/scanoss/api/vulnerabilities/v2/__init__.py +0 -0
  49. {scanoss-1.27.1 → scanoss-1.28.0}/src/scanoss/api/vulnerabilities/v2/scanoss_vulnerabilities_pb2.py +0 -0
  50. {scanoss-1.27.1 → scanoss-1.28.0}/src/scanoss/api/vulnerabilities/v2/scanoss_vulnerabilities_pb2_grpc.py +0 -0
  51. {scanoss-1.27.1 → scanoss-1.28.0}/src/scanoss/cli.py +0 -0
  52. {scanoss-1.27.1 → scanoss-1.28.0}/src/scanoss/components.py +0 -0
  53. {scanoss-1.27.1 → scanoss-1.28.0}/src/scanoss/constants.py +0 -0
  54. {scanoss-1.27.1 → scanoss-1.28.0}/src/scanoss/cryptography.py +0 -0
  55. {scanoss-1.27.1 → scanoss-1.28.0}/src/scanoss/csvoutput.py +0 -0
  56. {scanoss-1.27.1 → scanoss-1.28.0}/src/scanoss/data/scanoss-settings-schema.json +0 -0
  57. {scanoss-1.27.1 → scanoss-1.28.0}/src/scanoss/data/spdx-exceptions.json +0 -0
  58. {scanoss-1.27.1 → scanoss-1.28.0}/src/scanoss/data/spdx-licenses.json +0 -0
  59. {scanoss-1.27.1 → scanoss-1.28.0}/src/scanoss/file_filters.py +0 -0
  60. {scanoss-1.27.1 → scanoss-1.28.0}/src/scanoss/filecount.py +0 -0
  61. {scanoss-1.27.1 → scanoss-1.28.0}/src/scanoss/inspection/__init__.py +0 -0
  62. {scanoss-1.27.1 → scanoss-1.28.0}/src/scanoss/inspection/component_summary.py +0 -0
  63. {scanoss-1.27.1 → scanoss-1.28.0}/src/scanoss/inspection/copyleft.py +0 -0
  64. {scanoss-1.27.1 → scanoss-1.28.0}/src/scanoss/inspection/inspect_base.py +0 -0
  65. {scanoss-1.27.1 → scanoss-1.28.0}/src/scanoss/inspection/license_summary.py +0 -0
  66. {scanoss-1.27.1 → scanoss-1.28.0}/src/scanoss/inspection/policy_check.py +0 -0
  67. {scanoss-1.27.1 → scanoss-1.28.0}/src/scanoss/inspection/undeclared_component.py +0 -0
  68. {scanoss-1.27.1 → scanoss-1.28.0}/src/scanoss/inspection/utils/license_utils.py +0 -0
  69. {scanoss-1.27.1 → scanoss-1.28.0}/src/scanoss/results.py +0 -0
  70. {scanoss-1.27.1 → scanoss-1.28.0}/src/scanoss/scancodedeps.py +0 -0
  71. {scanoss-1.27.1 → scanoss-1.28.0}/src/scanoss/scanner.py +0 -0
  72. {scanoss-1.27.1 → scanoss-1.28.0}/src/scanoss/scanners/__init__.py +0 -0
  73. {scanoss-1.27.1 → scanoss-1.28.0}/src/scanoss/scanners/container_scanner.py +0 -0
  74. {scanoss-1.27.1 → scanoss-1.28.0}/src/scanoss/scanners/folder_hasher.py +0 -0
  75. {scanoss-1.27.1 → scanoss-1.28.0}/src/scanoss/scanners/scanner_config.py +0 -0
  76. {scanoss-1.27.1 → scanoss-1.28.0}/src/scanoss/scanoss_settings.py +0 -0
  77. {scanoss-1.27.1 → scanoss-1.28.0}/src/scanoss/scanossapi.py +0 -0
  78. {scanoss-1.27.1 → scanoss-1.28.0}/src/scanoss/scanossbase.py +0 -0
  79. {scanoss-1.27.1 → scanoss-1.28.0}/src/scanoss/scanpostprocessor.py +0 -0
  80. {scanoss-1.27.1 → scanoss-1.28.0}/src/scanoss/scantype.py +0 -0
  81. {scanoss-1.27.1 → scanoss-1.28.0}/src/scanoss/spdxlite.py +0 -0
  82. {scanoss-1.27.1 → scanoss-1.28.0}/src/scanoss/threadeddependencies.py +0 -0
  83. {scanoss-1.27.1 → scanoss-1.28.0}/src/scanoss/threadedscanning.py +0 -0
  84. {scanoss-1.27.1 → scanoss-1.28.0}/src/scanoss/utils/__init__.py +0 -0
  85. {scanoss-1.27.1 → scanoss-1.28.0}/src/scanoss/utils/abstract_presenter.py +0 -0
  86. {scanoss-1.27.1 → scanoss-1.28.0}/src/scanoss/utils/crc64.py +0 -0
  87. {scanoss-1.27.1 → scanoss-1.28.0}/src/scanoss/utils/file.py +0 -0
  88. {scanoss-1.27.1 → scanoss-1.28.0}/src/scanoss/utils/simhash.py +0 -0
  89. {scanoss-1.27.1 → scanoss-1.28.0}/src/scanoss/winnowing.py +0 -0
  90. {scanoss-1.27.1 → scanoss-1.28.0}/src/scanoss.egg-info/SOURCES.txt +0 -0
  91. {scanoss-1.27.1 → scanoss-1.28.0}/src/scanoss.egg-info/dependency_links.txt +0 -0
  92. {scanoss-1.27.1 → scanoss-1.28.0}/src/scanoss.egg-info/entry_points.txt +0 -0
  93. {scanoss-1.27.1 → scanoss-1.28.0}/src/scanoss.egg-info/requires.txt +0 -0
  94. {scanoss-1.27.1 → scanoss-1.28.0}/src/scanoss.egg-info/top_level.txt +0 -0
  95. {scanoss-1.27.1 → scanoss-1.28.0}/tests/test_csv_output.py +0 -0
  96. {scanoss-1.27.1 → scanoss-1.28.0}/tests/test_file_filters.py +0 -0
  97. {scanoss-1.27.1 → scanoss-1.28.0}/tests/test_policy_inspect.py +0 -0
  98. {scanoss-1.27.1 → scanoss-1.28.0}/tests/test_scan_post_processor.py +0 -0
  99. {scanoss-1.27.1 → scanoss-1.28.0}/tests/test_spdxlite.py +0 -0
  100. {scanoss-1.27.1 → scanoss-1.28.0}/tests/test_winnowing.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: scanoss
3
- Version: 1.27.1
3
+ Version: 1.28.0
4
4
  Summary: Simple Python library to leverage the SCANOSS APIs
5
5
  Home-page: https://scanoss.com
6
6
  Author: SCANOSS
@@ -22,4 +22,4 @@ SPDX-License-Identifier: MIT
22
22
  THE SOFTWARE.
23
23
  """
24
24
 
25
- __version__ = '1.27.1'
25
+ __version__ = '1.28.0'
@@ -287,6 +287,87 @@ class CycloneDx(ScanossBase):
287
287
  return False
288
288
  return self.produce_from_json(data, output_file)
289
289
 
290
+ def _normalize_vulnerability_id(self, vuln: dict) -> tuple[str, str]:
291
+ """
292
+ Normalize vulnerability ID and CVE from different possible field names.
293
+ Returns tuple of (vuln_id, vuln_cve).
294
+ """
295
+ vuln_id = vuln.get('ID', '') or vuln.get('id', '')
296
+ vuln_cve = vuln.get('CVE', '') or vuln.get('cve', '')
297
+
298
+ # Skip CPE entries, use CVE if available
299
+ if vuln_id.upper().startswith('CPE:') and vuln_cve:
300
+ vuln_id = vuln_cve
301
+
302
+ return vuln_id, vuln_cve
303
+
304
+ def _create_vulnerability_entry(self, vuln_id: str, vuln: dict, vuln_cve: str, purl: str) -> dict:
305
+ """
306
+ Create a new vulnerability entry for CycloneDX format.
307
+ """
308
+ vuln_source = vuln.get('source', '').lower()
309
+ return {
310
+ 'id': vuln_id,
311
+ 'source': {
312
+ 'name': 'NVD' if vuln_source == 'nvd' else 'GitHub Advisories',
313
+ 'url': f'https://nvd.nist.gov/vuln/detail/{vuln_cve}'
314
+ if vuln_source == 'nvd'
315
+ else f'https://github.com/advisories/{vuln_id}'
316
+ },
317
+ 'ratings': [{'severity': self._sev_lookup(vuln.get('severity', 'unknown').lower())}],
318
+ 'affects': [{'ref': purl}]
319
+ }
320
+
321
+ def append_vulnerabilities(self, cdx_dict: dict, vulnerabilities_data: dict, purl: str) -> dict:
322
+ """
323
+ Append vulnerabilities to an existing CycloneDX dictionary
324
+
325
+ Args:
326
+ cdx_dict (dict): The existing CycloneDX dictionary
327
+ vulnerabilities_data (dict): The vulnerabilities data from get_vulnerabilities_json
328
+ purl (str): The PURL of the component these vulnerabilities affect
329
+
330
+ Returns:
331
+ dict: The updated CycloneDX dictionary with vulnerabilities appended
332
+ """
333
+ if not cdx_dict or not vulnerabilities_data:
334
+ return cdx_dict
335
+
336
+ if 'vulnerabilities' not in cdx_dict:
337
+ cdx_dict['vulnerabilities'] = []
338
+
339
+ # Extract vulnerabilities from the response
340
+ vulns_list = vulnerabilities_data.get('purls', [])
341
+ if not vulns_list:
342
+ return cdx_dict
343
+
344
+ vuln_items = vulns_list[0].get('vulnerabilities', [])
345
+
346
+ for vuln in vuln_items:
347
+ vuln_id, vuln_cve = self._normalize_vulnerability_id(vuln)
348
+
349
+ # Skip empty IDs or CPE-only entries
350
+ if not vuln_id or vuln_id.upper().startswith('CPE:'):
351
+ continue
352
+
353
+ # Check if vulnerability already exists
354
+ existing_vuln = next(
355
+ (v for v in cdx_dict['vulnerabilities'] if v.get('id') == vuln_id),
356
+ None
357
+ )
358
+
359
+ if existing_vuln:
360
+ # Add this PURL to the affects list if not already present
361
+ if not any(ref.get('ref') == purl for ref in existing_vuln.get('affects', [])):
362
+ existing_vuln['affects'].append({'ref': purl})
363
+ else:
364
+ # Create new vulnerability entry
365
+ cdx_dict['vulnerabilities'].append(
366
+ self._create_vulnerability_entry(vuln_id, vuln, vuln_cve, purl)
367
+ )
368
+
369
+ return cdx_dict
370
+
290
371
  @staticmethod
291
372
  def _sev_lookup(value: str):
292
373
  """
@@ -0,0 +1 @@
1
+ date: 20250710142446, utime: 1752157486
@@ -193,8 +193,13 @@ class ScannerHFHPresenter(AbstractPresenter):
193
193
  }
194
194
  ]
195
195
  }
196
+
197
+ get_vulnerabilities_json_request = {
198
+ 'purls': [{'purl': purl, 'requirement': best_match_version['version']}],
199
+ }
196
200
 
197
201
  decorated_scan_results = self.scanner.client.get_dependencies(get_dependencies_json_request)
202
+ vulnerabilities = self.scanner.client.get_vulnerabilities_json(get_vulnerabilities_json_request)
198
203
 
199
204
  cdx = CycloneDx(self.base.debug)
200
205
  scan_results = {}
@@ -205,6 +210,10 @@ class ScannerHFHPresenter(AbstractPresenter):
205
210
  error_msg = 'ERROR: Failed to produce CycloneDX output'
206
211
  self.base.print_stderr(error_msg)
207
212
  return None
213
+
214
+ if vulnerabilities:
215
+ cdx_output = cdx.append_vulnerabilities(cdx_output, vulnerabilities, purl)
216
+
208
217
  return json.dumps(cdx_output, indent=2)
209
218
  except Exception as e:
210
219
  self.base.print_stderr(f'ERROR: Failed to get license information: {e}')
@@ -326,7 +326,7 @@ class ScanossGrpc(ScanossBase):
326
326
  request = ParseDict(purls, PurlRequest()) # Parse the JSON/Dict into the purl request object
327
327
  metadata = self.metadata[:]
328
328
  metadata.append(('x-request-id', request_id)) # Set a Request ID
329
- self.print_debug(f'Sending crypto data for decoration (rqId: {request_id})...')
329
+ self.print_debug(f'Sending vulnerability data for decoration (rqId: {request_id})...')
330
330
  resp = self.vuln_stub.GetVulnerabilities(request, metadata=metadata, timeout=self.timeout)
331
331
  except Exception as e:
332
332
  self.print_stderr(
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: scanoss
3
- Version: 1.27.1
3
+ Version: 1.28.0
4
4
  Summary: Simple Python library to leverage the SCANOSS APIs
5
5
  Home-page: https://scanoss.com
6
6
  Author: SCANOSS
@@ -1 +0,0 @@
1
- date: 20250709092546, utime: 1752053146
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes