fosslight-binary 5.1.24__tar.gz → 5.1.26__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 (113) hide show
  1. {fosslight_binary-5.1.24 → fosslight_binary-5.1.26}/PKG-INFO +2 -1
  2. {fosslight_binary-5.1.24 → fosslight_binary-5.1.26}/pyproject.toml +3 -8
  3. fosslight_binary-5.1.26/src/fosslight_binary/__init__.py +4 -0
  4. {fosslight_binary-5.1.24 → fosslight_binary-5.1.26}/src/fosslight_binary/_binary.py +3 -27
  5. {fosslight_binary-5.1.24 → fosslight_binary-5.1.26}/src/fosslight_binary/_binary_dao.py +2 -2
  6. fosslight_binary-5.1.26/src/fosslight_binary/_jar_analysis.py +407 -0
  7. {fosslight_binary-5.1.24 → fosslight_binary-5.1.26}/src/fosslight_binary/binary_analysis.py +17 -18
  8. {fosslight_binary-5.1.24 → fosslight_binary-5.1.26}/src/fosslight_binary.egg-info/PKG-INFO +2 -1
  9. fosslight_binary-5.1.26/src/fosslight_binary.egg-info/SOURCES.txt +22 -0
  10. {fosslight_binary-5.1.24 → fosslight_binary-5.1.26}/src/fosslight_binary.egg-info/requires.txt +1 -0
  11. fosslight_binary-5.1.24/src/fosslight_binary/__init__.py +0 -79
  12. fosslight_binary-5.1.24/src/fosslight_binary/_jar_analysis.py +0 -311
  13. fosslight_binary-5.1.24/src/fosslight_binary/third_party/dependency-check/LICENSE.txt +0 -202
  14. fosslight_binary-5.1.24/src/fosslight_binary/third_party/dependency-check/NOTICE.txt +0 -18
  15. fosslight_binary-5.1.24/src/fosslight_binary/third_party/dependency-check/README.md +0 -20
  16. fosslight_binary-5.1.24/src/fosslight_binary/third_party/dependency-check/bin/completion-for-dependency-check.sh +0 -150
  17. fosslight_binary-5.1.24/src/fosslight_binary/third_party/dependency-check/bin/dependency-check.bat +0 -110
  18. fosslight_binary-5.1.24/src/fosslight_binary/third_party/dependency-check/bin/dependency-check.sh +0 -135
  19. fosslight_binary-5.1.24/src/fosslight_binary/third_party/dependency-check/lib/aho-corasick-double-array-trie-1.2.3.jar +0 -0
  20. fosslight_binary-5.1.24/src/fosslight_binary/third_party/dependency-check/lib/android-json-0.0.20131108.vaadin1.jar +0 -0
  21. fosslight_binary-5.1.24/src/fosslight_binary/third_party/dependency-check/lib/annotations-26.0.2-1.jar +0 -0
  22. fosslight_binary-5.1.24/src/fosslight_binary/third_party/dependency-check/lib/ant-1.10.15.jar +0 -0
  23. fosslight_binary-5.1.24/src/fosslight_binary/third_party/dependency-check/lib/bcpg-jdk18on-1.78.jar +0 -0
  24. fosslight_binary-5.1.24/src/fosslight_binary/third_party/dependency-check/lib/bcprov-jdk18on-1.78.jar +0 -0
  25. fosslight_binary-5.1.24/src/fosslight_binary/third_party/dependency-check/lib/commons-cli-1.10.0.jar +0 -0
  26. fosslight_binary-5.1.24/src/fosslight_binary/third_party/dependency-check/lib/commons-codec-1.19.0.jar +0 -0
  27. fosslight_binary-5.1.24/src/fosslight_binary/third_party/dependency-check/lib/commons-collections-3.2.2.jar +0 -0
  28. fosslight_binary-5.1.24/src/fosslight_binary/third_party/dependency-check/lib/commons-collections4-4.5.0.jar +0 -0
  29. fosslight_binary-5.1.24/src/fosslight_binary/third_party/dependency-check/lib/commons-compress-1.27.1.jar +0 -0
  30. fosslight_binary-5.1.24/src/fosslight_binary/third_party/dependency-check/lib/commons-dbcp2-2.13.0.jar +0 -0
  31. fosslight_binary-5.1.24/src/fosslight_binary/third_party/dependency-check/lib/commons-digester-2.1.jar +0 -0
  32. fosslight_binary-5.1.24/src/fosslight_binary/third_party/dependency-check/lib/commons-io-2.20.0.jar +0 -0
  33. fosslight_binary-5.1.24/src/fosslight_binary/third_party/dependency-check/lib/commons-jcs3-core-3.2.1.jar +0 -0
  34. fosslight_binary-5.1.24/src/fosslight_binary/third_party/dependency-check/lib/commons-lang3-3.19.0.jar +0 -0
  35. fosslight_binary-5.1.24/src/fosslight_binary/third_party/dependency-check/lib/commons-logging-1.3.4.jar +0 -0
  36. fosslight_binary-5.1.24/src/fosslight_binary/third_party/dependency-check/lib/commons-pool2-2.12.0.jar +0 -0
  37. fosslight_binary-5.1.24/src/fosslight_binary/third_party/dependency-check/lib/commons-text-1.14.0.jar +0 -0
  38. fosslight_binary-5.1.24/src/fosslight_binary/third_party/dependency-check/lib/commons-validator-1.10.0.jar +0 -0
  39. fosslight_binary-5.1.24/src/fosslight_binary/third_party/dependency-check/lib/compiler-0.9.6.jar +0 -0
  40. fosslight_binary-5.1.24/src/fosslight_binary/third_party/dependency-check/lib/cpe-parser-3.0.0.jar +0 -0
  41. fosslight_binary-5.1.24/src/fosslight_binary/third_party/dependency-check/lib/dependency-check-cli-12.1.7.jar +0 -0
  42. fosslight_binary-5.1.24/src/fosslight_binary/third_party/dependency-check/lib/dependency-check-core-12.1.7.jar +0 -0
  43. fosslight_binary-5.1.24/src/fosslight_binary/third_party/dependency-check/lib/dependency-check-utils-12.1.7.jar +0 -0
  44. fosslight_binary-5.1.24/src/fosslight_binary/third_party/dependency-check/lib/error_prone_annotations-2.41.0.jar +0 -0
  45. fosslight_binary-5.1.24/src/fosslight_binary/third_party/dependency-check/lib/failureaccess-1.0.3.jar +0 -0
  46. fosslight_binary-5.1.24/src/fosslight_binary/third_party/dependency-check/lib/gson-2.9.0.jar +0 -0
  47. fosslight_binary-5.1.24/src/fosslight_binary/third_party/dependency-check/lib/guava-33.5.0-jre.jar +0 -0
  48. fosslight_binary-5.1.24/src/fosslight_binary/third_party/dependency-check/lib/h2-2.3.232.jar +0 -0
  49. fosslight_binary-5.1.24/src/fosslight_binary/third_party/dependency-check/lib/httpclient5-5.5.jar +0 -0
  50. fosslight_binary-5.1.24/src/fosslight_binary/third_party/dependency-check/lib/httpclient5-cache-5.4.3.jar +0 -0
  51. fosslight_binary-5.1.24/src/fosslight_binary/third_party/dependency-check/lib/httpcore5-5.3.6.jar +0 -0
  52. fosslight_binary-5.1.24/src/fosslight_binary/third_party/dependency-check/lib/httpcore5-h2-5.3.4.jar +0 -0
  53. fosslight_binary-5.1.24/src/fosslight_binary/third_party/dependency-check/lib/j2objc-annotations-3.1.jar +0 -0
  54. fosslight_binary-5.1.24/src/fosslight_binary/third_party/dependency-check/lib/jackson-annotations-2.20.jar +0 -0
  55. fosslight_binary-5.1.24/src/fosslight_binary/third_party/dependency-check/lib/jackson-core-2.20.0.jar +0 -0
  56. fosslight_binary-5.1.24/src/fosslight_binary/third_party/dependency-check/lib/jackson-databind-2.20.0.jar +0 -0
  57. fosslight_binary-5.1.24/src/fosslight_binary/third_party/dependency-check/lib/jackson-dataformat-yaml-2.20.0.jar +0 -0
  58. fosslight_binary-5.1.24/src/fosslight_binary/third_party/dependency-check/lib/jackson-datatype-jsr310-2.20.0.jar +0 -0
  59. fosslight_binary-5.1.24/src/fosslight_binary/third_party/dependency-check/lib/jackson-module-blackbird-2.20.0.jar +0 -0
  60. fosslight_binary-5.1.24/src/fosslight_binary/third_party/dependency-check/lib/jakarta.json-2.0.1.jar +0 -0
  61. fosslight_binary-5.1.24/src/fosslight_binary/third_party/dependency-check/lib/jakarta.transaction-api-1.3.3.jar +0 -0
  62. fosslight_binary-5.1.24/src/fosslight_binary/third_party/dependency-check/lib/javax.activation-api-1.2.0.jar +0 -0
  63. fosslight_binary-5.1.24/src/fosslight_binary/third_party/dependency-check/lib/javax.inject-1.jar +0 -0
  64. fosslight_binary-5.1.24/src/fosslight_binary/third_party/dependency-check/lib/javax.ws.rs-api-2.0.1.jar +0 -0
  65. fosslight_binary-5.1.24/src/fosslight_binary/third_party/dependency-check/lib/jaxb-api-2.3.1.jar +0 -0
  66. fosslight_binary-5.1.24/src/fosslight_binary/third_party/dependency-check/lib/jcs3-slf4j-1.0.5.jar +0 -0
  67. fosslight_binary-5.1.24/src/fosslight_binary/third_party/dependency-check/lib/jdiagnostics-1.0.7.jar +0 -0
  68. fosslight_binary-5.1.24/src/fosslight_binary/third_party/dependency-check/lib/jmustache-1.16.jar +0 -0
  69. fosslight_binary-5.1.24/src/fosslight_binary/third_party/dependency-check/lib/joda-time-2.14.0.jar +0 -0
  70. fosslight_binary-5.1.24/src/fosslight_binary/third_party/dependency-check/lib/jsoup-1.21.2.jar +0 -0
  71. fosslight_binary-5.1.24/src/fosslight_binary/third_party/dependency-check/lib/jspecify-1.0.0.jar +0 -0
  72. fosslight_binary-5.1.24/src/fosslight_binary/third_party/dependency-check/lib/jsr305-3.0.2.jar +0 -0
  73. fosslight_binary-5.1.24/src/fosslight_binary/third_party/dependency-check/lib/jul-to-slf4j-1.7.36.jar +0 -0
  74. fosslight_binary-5.1.24/src/fosslight_binary/third_party/dependency-check/lib/listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar +0 -0
  75. fosslight_binary-5.1.24/src/fosslight_binary/third_party/dependency-check/lib/logback-classic-1.2.13.jar +0 -0
  76. fosslight_binary-5.1.24/src/fosslight_binary/third_party/dependency-check/lib/logback-core-1.2.13.jar +0 -0
  77. fosslight_binary-5.1.24/src/fosslight_binary/third_party/dependency-check/lib/lucene-analysis-common-9.12.0.jar +0 -0
  78. fosslight_binary-5.1.24/src/fosslight_binary/third_party/dependency-check/lib/lucene-core-9.12.0.jar +0 -0
  79. fosslight_binary-5.1.24/src/fosslight_binary/third_party/dependency-check/lib/lucene-facet-9.12.0.jar +0 -0
  80. fosslight_binary-5.1.24/src/fosslight_binary/third_party/dependency-check/lib/lucene-queries-9.12.0.jar +0 -0
  81. fosslight_binary-5.1.24/src/fosslight_binary/third_party/dependency-check/lib/lucene-queryparser-9.12.0.jar +0 -0
  82. fosslight_binary-5.1.24/src/fosslight_binary/third_party/dependency-check/lib/lucene-sandbox-9.12.0.jar +0 -0
  83. fosslight_binary-5.1.24/src/fosslight_binary/third_party/dependency-check/lib/minlog-1.3.1.jar +0 -0
  84. fosslight_binary-5.1.24/src/fosslight_binary/third_party/dependency-check/lib/open-vulnerability-clients-7.3.2.jar +0 -0
  85. fosslight_binary-5.1.24/src/fosslight_binary/third_party/dependency-check/lib/ossindex-service-api-1.8.2.jar +0 -0
  86. fosslight_binary-5.1.24/src/fosslight_binary/third_party/dependency-check/lib/ossindex-service-client-1.8.2.jar +0 -0
  87. fosslight_binary-5.1.24/src/fosslight_binary/third_party/dependency-check/lib/package-url-java-1.2.0.jar +0 -0
  88. fosslight_binary-5.1.24/src/fosslight_binary/third_party/dependency-check/lib/packager-core-0.21.0.jar +0 -0
  89. fosslight_binary-5.1.24/src/fosslight_binary/third_party/dependency-check/lib/packager-rpm-0.21.0.jar +0 -0
  90. fosslight_binary-5.1.24/src/fosslight_binary/third_party/dependency-check/lib/packageurl-java-1.5.0.jar +0 -0
  91. fosslight_binary-5.1.24/src/fosslight_binary/third_party/dependency-check/lib/pecoff4j-0.0.2.1.jar +0 -0
  92. fosslight_binary-5.1.24/src/fosslight_binary/third_party/dependency-check/lib/retirejs-core-3.0.4.jar +0 -0
  93. fosslight_binary-5.1.24/src/fosslight_binary/third_party/dependency-check/lib/semver4j-5.8.0.jar +0 -0
  94. fosslight_binary-5.1.24/src/fosslight_binary/third_party/dependency-check/lib/slf4j-api-1.7.36.jar +0 -0
  95. fosslight_binary-5.1.24/src/fosslight_binary/third_party/dependency-check/lib/snakeyaml-2.4.jar +0 -0
  96. fosslight_binary-5.1.24/src/fosslight_binary/third_party/dependency-check/lib/spotbugs-annotations-4.9.6.jar +0 -0
  97. fosslight_binary-5.1.24/src/fosslight_binary/third_party/dependency-check/lib/toml4j-0.7.2.jar +0 -0
  98. fosslight_binary-5.1.24/src/fosslight_binary/third_party/dependency-check/lib/velocity-engine-core-2.4.1.jar +0 -0
  99. fosslight_binary-5.1.24/src/fosslight_binary/third_party/dependency-check/lib/xz-1.9.jar +0 -0
  100. fosslight_binary-5.1.24/src/fosslight_binary.egg-info/SOURCES.txt +0 -109
  101. {fosslight_binary-5.1.24 → fosslight_binary-5.1.26}/LICENSE +0 -0
  102. {fosslight_binary-5.1.24 → fosslight_binary-5.1.26}/LICENSES/Apache-2.0.txt +0 -0
  103. {fosslight_binary-5.1.24 → fosslight_binary-5.1.26}/LICENSES/LicenseRef-3rd_party_licenses.txt +0 -0
  104. {fosslight_binary-5.1.24 → fosslight_binary-5.1.26}/MANIFEST.in +0 -0
  105. {fosslight_binary-5.1.24 → fosslight_binary-5.1.26}/README.md +0 -0
  106. {fosslight_binary-5.1.24 → fosslight_binary-5.1.26}/setup.cfg +0 -0
  107. {fosslight_binary-5.1.24 → fosslight_binary-5.1.26}/src/fosslight_binary/_help.py +0 -0
  108. {fosslight_binary-5.1.24 → fosslight_binary-5.1.26}/src/fosslight_binary/_simple_mode.py +0 -0
  109. {fosslight_binary-5.1.24 → fosslight_binary-5.1.26}/src/fosslight_binary/cli.py +0 -0
  110. {fosslight_binary-5.1.24 → fosslight_binary-5.1.26}/src/fosslight_binary.egg-info/dependency_links.txt +0 -0
  111. {fosslight_binary-5.1.24 → fosslight_binary-5.1.26}/src/fosslight_binary.egg-info/entry_points.txt +0 -0
  112. {fosslight_binary-5.1.24 → fosslight_binary-5.1.26}/src/fosslight_binary.egg-info/top_level.txt +0 -0
  113. {fosslight_binary-5.1.24 → fosslight_binary-5.1.26}/tests/test_fosslight_binary.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fosslight_binary
3
- Version: 5.1.24
3
+ Version: 5.1.26
4
4
  Summary: FOSSLight Binary Scanner
5
5
  Author: LG Electronics
6
6
  License-Expression: Apache-2.0
@@ -20,6 +20,7 @@ License-File: LICENSES/Apache-2.0.txt
20
20
  License-File: LICENSES/LicenseRef-3rd_party_licenses.txt
21
21
  Requires-Dist: binaryornot==0.4.4
22
22
  Requires-Dist: chardet<5.0.0
23
+ Requires-Dist: defusedxml
23
24
  Requires-Dist: numpy
24
25
  Requires-Dist: pandas
25
26
  Requires-Dist: parmap
@@ -7,7 +7,7 @@ build-backend = "setuptools.build_meta"
7
7
 
8
8
  [project]
9
9
  name = "fosslight_binary"
10
- version = "5.1.24"
10
+ version = "5.1.26"
11
11
  description = "FOSSLight Binary Scanner"
12
12
  readme = "README.md"
13
13
  license = "Apache-2.0"
@@ -27,6 +27,7 @@ requires-python = ">=3.10,<3.15"
27
27
  dependencies = [
28
28
  "binaryornot==0.4.4",
29
29
  "chardet<5.0.0",
30
+ "defusedxml",
30
31
  "numpy",
31
32
  "pandas",
32
33
  "parmap",
@@ -58,10 +59,4 @@ package-dir = {"" = "src"}
58
59
  where = ["src"]
59
60
 
60
61
  [tool.setuptools.package-data]
61
- fosslight_binary = [
62
- "third_party/dependency-check/bin/*",
63
- "third_party/dependency-check/lib/*",
64
- "third_party/dependency-check/licenses/*",
65
- "third_party/dependency-check/*.txt",
66
- "third_party/dependency-check/*.md",
67
- ]
62
+ fosslight_binary = []
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env python
2
+ # -*- coding: utf-8 -*-
3
+ # Copyright (c) 2025 LG Electronics Inc.
4
+ # SPDX-License-Identifier: Apache-2.0
@@ -2,41 +2,26 @@
2
2
  # -*- coding: utf-8 -*-
3
3
  # Copyright (c) 2020 LG Electronics Inc.
4
4
  # SPDX-License-Identifier: Apache-2.0
5
- import urllib.parse
6
5
  import logging
7
6
  import fosslight_util.constant as constant
8
7
  from fosslight_util.oss_item import FileItem
9
8
 
10
9
  EXCLUDE_TRUE_VALUE = "Exclude"
11
10
  TLSH_CHECKSUM_NULL = "0"
12
- MAX_EXCEL_URL_LENGTH = 255
13
- EXCEEDED_VUL_URL_LENGTH_COMMENT = f"Exceeded the maximum vulnerability URL length of {MAX_EXCEL_URL_LENGTH} characters."
14
11
 
15
12
  logger = logging.getLogger(constant.LOGGER_NAME)
16
13
 
17
14
 
18
- class VulnerabilityItem:
19
- file_path = ""
20
- vul_id = ""
21
- nvd_url = ""
22
-
23
- def __init__(self, file_path, id, url):
24
- self.file_path = file_path
25
- self.vul_id = id
26
- self.nvd_url = url
27
-
28
-
29
15
  class BinaryItem(FileItem):
30
16
  def __init__(self, value):
31
17
  super().__init__("")
32
18
  self.exclude = False
33
19
  self.source_name_or_path = ""
34
20
  self.tlsh = TLSH_CHECKSUM_NULL
35
- self.vulnerability_items = []
36
21
  self.binary_name_without_path = ""
37
22
  self.bin_name_with_path = value
38
23
  self.is_binary = True
39
- self.found_in_owasp = False
24
+ self.found_in_jar_analysis = False
40
25
  self.found_in_bin_db = False # for debugging
41
26
 
42
27
  def __del__(self):
@@ -50,29 +35,20 @@ class BinaryItem(FileItem):
50
35
  # Append New input OSS
51
36
  self.oss_items.extend(new_oss_list)
52
37
 
53
- def get_vulnerability_items(self, oss):
54
- nvd_url = set([urllib.parse.unquote(vul_item.nvd_url) for vul_item in self.vulnerability_items])
55
- nvd_url = ", ".join(nvd_url).strip()
56
-
57
- if nvd_url and len(nvd_url) > MAX_EXCEL_URL_LENGTH:
58
- oss.comment = EXCEEDED_VUL_URL_LENGTH_COMMENT
59
- return nvd_url
60
-
61
38
  def get_print_array(self):
62
39
  items = []
63
40
  if self.oss_items:
64
41
  for oss in self.oss_items:
65
42
  lic = ",".join(oss.license)
66
43
  exclude = EXCLUDE_TRUE_VALUE if (self.exclude or oss.exclude) else ""
67
- nvd_url = self.get_vulnerability_items(oss)
68
44
  items.append([self.source_name_or_path, oss.name, oss.version,
69
45
  lic, oss.download_location, oss.homepage,
70
46
  oss.copyright, exclude, oss.comment,
71
- nvd_url, self.tlsh, self.checksum])
47
+ self.tlsh, self.checksum])
72
48
  else:
73
49
  exclude = EXCLUDE_TRUE_VALUE if self.exclude else ""
74
50
  items.append([self.source_name_or_path, '',
75
- '', '', '', '', '', exclude, self.comment, '',
51
+ '', '', '', '', '', exclude, self.comment,
76
52
  self.tlsh, self.checksum])
77
53
  return items
78
54
 
@@ -55,11 +55,11 @@ def get_oss_info_from_db(bin_info_list, dburl=""):
55
55
  if df_result is not None and len(df_result) > 0:
56
56
  _cnt_auto_identified += 1
57
57
  # Initialize the saved contents at .jar analyzing only once
58
- if not item.found_in_owasp and item.oss_items:
58
+ if not item.found_in_jar_analysis and item.oss_items:
59
59
  item.oss_items = []
60
60
 
61
61
  for idx, row in df_result.iterrows():
62
- if not item.found_in_owasp:
62
+ if not item.found_in_jar_analysis:
63
63
  oss_from_db = OssItem(row['ossname'], row['ossversion'], row['license'])
64
64
 
65
65
  if bin_oss_items:
@@ -0,0 +1,407 @@
1
+ #!/usr/bin/env python
2
+ # -*- coding: utf-8 -*-
3
+ # Copyright (c) 2022 LG Electronics Inc.
4
+ # SPDX-License-Identifier: Apache-2.0
5
+
6
+
7
+ import hashlib
8
+ import logging
9
+ import os
10
+ import tempfile
11
+ import zipfile
12
+ import defusedxml.ElementTree as ET
13
+ import requests
14
+ import fosslight_util.constant as constant
15
+ from fosslight_util.get_pom_license import get_license_from_pom
16
+ from fosslight_binary._binary import BinaryItem
17
+ from fosslight_util.oss_item import OssItem
18
+
19
+ logger = logging.getLogger(constant.LOGGER_NAME)
20
+
21
+ _CENTRAL_SEARCH_URL = "https://search.maven.org/solrsearch/select"
22
+ _REQUEST_TIMEOUT = 10 # seconds – used for HEAD / POM download
23
+ _CENTRAL_SEARCH_TIMEOUT = 2.5 # seconds – tight timeout for Search API (retried on timeout)
24
+ _MAX_RETRY = 3 # maximum Central API retry attempts per JAR
25
+ _central_network_warned = False # Flag to suppress repeated network-unavailable warnings within one run
26
+
27
+
28
+ def _sha1_of_file(filepath):
29
+ h = hashlib.sha1()
30
+ try:
31
+ with open(filepath, 'rb') as f:
32
+ for chunk in iter(lambda: f.read(65536), b''):
33
+ h.update(chunk)
34
+ except Exception as ex:
35
+ logger.debug(f"SHA-1 computation failed for {filepath}: {ex}")
36
+ return ""
37
+ return h.hexdigest()
38
+
39
+
40
+ def _parse_pom_bytes(pom_bytes):
41
+ try:
42
+ root = ET.fromstring(pom_bytes)
43
+ ns = root.tag.split('}')[0] + '}' if root.tag.startswith('{') else ''
44
+ groupId = root.findtext(f'{ns}groupId') or root.findtext(f'{ns}parent/{ns}groupId') or ''
45
+ artifactId = root.findtext(f'{ns}artifactId') or ''
46
+ version = root.findtext(f'{ns}version') or root.findtext(f'{ns}parent/{ns}version') or ''
47
+ project_url = root.findtext(f'{ns}url') or ''
48
+ return groupId, artifactId, version, project_url
49
+ except Exception as ex:
50
+ logger.debug(f"POM parse error: {ex}")
51
+ return '', '', '', ''
52
+
53
+
54
+ def _parse_manifest_bytes(manifest_bytes):
55
+ info = {}
56
+ for line in manifest_bytes.decode('utf-8', errors='replace').splitlines():
57
+ if ':' in line:
58
+ k, _, v = line.partition(':')
59
+ info[k.strip()] = v.strip()
60
+ return info
61
+
62
+
63
+ def _read_pom_from_jar(jar_path):
64
+ try:
65
+ with zipfile.ZipFile(jar_path, 'r') as jar:
66
+ pom_candidates = [n for n in jar.namelist()
67
+ if n.startswith('META-INF/maven') and n.endswith('pom.xml')]
68
+ if not pom_candidates:
69
+ return '', '', '', '', None
70
+ pom_bytes = jar.open(pom_candidates[0]).read()
71
+ groupId, artifactId, version, project_url = _parse_pom_bytes(pom_bytes)
72
+ with tempfile.NamedTemporaryFile(suffix='.pom', delete=False, mode='wb') as tmp:
73
+ tmp.write(pom_bytes)
74
+ pom_tmp_path = tmp.name
75
+ return groupId, artifactId, version, project_url, pom_tmp_path
76
+ except Exception as ex:
77
+ logger.debug(f"JAR pom.xml read failed for {jar_path}: {ex}")
78
+ return '', '', '', '', None
79
+
80
+
81
+ def _read_manifest_from_jar(jar_path):
82
+ try:
83
+ with zipfile.ZipFile(jar_path, 'r') as jar:
84
+ if 'META-INF/MANIFEST.MF' not in jar.namelist():
85
+ return '', '', '', ''
86
+ mf = _parse_manifest_bytes(jar.open('META-INF/MANIFEST.MF').read())
87
+ groupId = mf.get('Bundle-Vendor', '') or mf.get('Implementation-Vendor', '')
88
+ artifactId = mf.get('Bundle-SymbolicName', '') or mf.get('Implementation-Title', '')
89
+ version = mf.get('Bundle-Version', '') or mf.get('Implementation-Version', '')
90
+ project_url = mf.get('Bundle-DocURL', '') or mf.get('Implementation-URL', '')
91
+ return groupId, artifactId, version, project_url
92
+ except Exception as ex:
93
+ logger.debug(f"JAR MANIFEST.MF read failed for {jar_path}: {ex}")
94
+ return '', '', '', ''
95
+
96
+
97
+ def _is_network_error(ex):
98
+ return isinstance(ex, (
99
+ requests.exceptions.ConnectionError,
100
+ requests.exceptions.Timeout,
101
+ requests.exceptions.SSLError,
102
+ ))
103
+
104
+
105
+ def _warn_network_once(context=""):
106
+ global _central_network_warned
107
+ if not _central_network_warned:
108
+ msg = "Maven Central API에 접속할 수 없어 분석에 실패했습니다"
109
+ if context:
110
+ msg += f" ({context})"
111
+ logger.warning(msg)
112
+ _central_network_warned = True
113
+
114
+
115
+ def _search_central_by_sha1(sha1, timeout=None):
116
+ if not sha1:
117
+ return {}, False
118
+ _timeout = timeout if timeout is not None else _CENTRAL_SEARCH_TIMEOUT
119
+ try:
120
+ params = {"q": f"1:{sha1}", "rows": 1, "wt": "json"}
121
+ resp = requests.get(_CENTRAL_SEARCH_URL, params=params, timeout=_timeout)
122
+ resp.raise_for_status()
123
+ docs = resp.json().get("response", {}).get("docs", [])
124
+ if not docs:
125
+ return {}, False
126
+ doc = docs[0]
127
+ return {
128
+ "groupId": doc.get("g", ""),
129
+ "artifactId": doc.get("a", ""),
130
+ "version": doc.get("v") or doc.get("latestVersion", ""),
131
+ }, False
132
+ except requests.exceptions.Timeout:
133
+ logger.debug(f"Maven Central SHA-1 search timed out ({sha1}) – will retry")
134
+ return {}, True
135
+ except Exception as ex:
136
+ if _is_network_error(ex):
137
+ _warn_network_once(f"SHA-1 search: {sha1[:10]}...")
138
+ else:
139
+ logger.debug(f"Maven Central SHA-1 search failed ({sha1}): {ex}")
140
+ return {}, False
141
+
142
+
143
+ def _download_pom_to_tempfile(group_id, artifact_id, version, timeout=None):
144
+ _timeout = timeout if timeout is not None else _REQUEST_TIMEOUT
145
+ group_path = group_id.replace('.', '/')
146
+ pom_name = f"{artifact_id}-{version}.pom"
147
+ urls = [
148
+ f"https://repo1.maven.org/maven2/{group_path}/{artifact_id}/{version}/{pom_name}",
149
+ f"https://dl.google.com/android/maven2/{group_path}/{artifact_id}/{version}/{pom_name}",
150
+ ]
151
+ any_timeout = False
152
+ for url in urls:
153
+ try:
154
+ resp = requests.get(url, timeout=_timeout)
155
+ resp.raise_for_status()
156
+ with tempfile.NamedTemporaryFile(suffix='.pom', delete=False, mode='wb') as tmp:
157
+ tmp.write(resp.content)
158
+ logger.debug(f"POM downloaded to {tmp.name} from {url}")
159
+ return tmp.name, False
160
+ except requests.exceptions.Timeout:
161
+ logger.debug(f"POM download timed out from {url} – will retry")
162
+ any_timeout = True
163
+ except Exception as ex:
164
+ if _is_network_error(ex):
165
+ _warn_network_once(f"POM download: {group_id}:{artifact_id}:{version}")
166
+ else:
167
+ logger.debug(f"POM download failed from {url}: {ex}")
168
+ return None, any_timeout
169
+
170
+
171
+ def _build_central_jar_url(group_id, artifact_id, version):
172
+ if not (group_id and artifact_id and version):
173
+ return ""
174
+ group_path = group_id.replace('.', '/')
175
+ return f"https://repo1.maven.org/maven2/{group_path}/{artifact_id}/{version}/{artifact_id}-{version}.jar"
176
+
177
+
178
+ def _exists_in_central(group_id, artifact_id, version):
179
+ if not (group_id and artifact_id and version):
180
+ return False
181
+ url = _build_central_jar_url(group_id, artifact_id, version)
182
+ try:
183
+ resp = requests.head(url, timeout=_REQUEST_TIMEOUT, allow_redirects=True)
184
+ return resp.status_code == 200
185
+ except Exception as ex:
186
+ if _is_network_error(ex):
187
+ _warn_network_once(f"existence check: {group_id}:{artifact_id}:{version}")
188
+ else:
189
+ logger.debug(f"Central existence check failed ({group_id}:{artifact_id}:{version}): {ex}")
190
+ return False
191
+
192
+
193
+ def _process_one_jar(jar_path, rel_path, sha1, search_timeout=None, skip_central=False):
194
+ groupId = artifactId = version = project_url = license_str = ''
195
+ confirmed_in_central = False
196
+ source = ''
197
+
198
+ if skip_central:
199
+ central_info = {}
200
+ timed_out = False
201
+ else:
202
+ central_info, timed_out = _search_central_by_sha1(sha1, timeout=search_timeout)
203
+ if timed_out:
204
+ logger.debug(f"{rel_path}: Central SHA-1 search timed out – will retry")
205
+ return None, True
206
+
207
+ g2, a2, v2, url2, pom_tmp_path = _read_pom_from_jar(jar_path)
208
+
209
+ if central_info:
210
+ c_groupId = central_info['groupId']
211
+ c_artifactId = central_info['artifactId']
212
+ c_version = central_info['version']
213
+
214
+ jar_oss_name = f"{g2}:{a2}"
215
+ central_oss_name = f"{c_groupId}:{c_artifactId}"
216
+ names_match = (central_oss_name == jar_oss_name and c_version == v2)
217
+
218
+ if names_match:
219
+ logger.debug(f"{rel_path}: Central and JAR pom.xml match ({central_oss_name} {c_version}) – using JAR pom.xml for license")
220
+ groupId, artifactId, version, project_url = g2, a2, v2, url2
221
+ source = 'pom.xml'
222
+ confirmed_in_central = True
223
+
224
+ if pom_tmp_path:
225
+ try:
226
+ license_str = get_license_from_pom(
227
+ group_id=groupId, artifact_id=artifactId, version=version,
228
+ pom_path=pom_tmp_path, check_parent=True)
229
+ logger.debug(f"{rel_path}: license from JAR pom.xml (matched Central)={license_str!r}")
230
+ except Exception as ex:
231
+ logger.debug(f"get_license_from_pom (jar pom_path) failed: {ex}")
232
+ finally:
233
+ try:
234
+ os.remove(pom_tmp_path)
235
+ except Exception:
236
+ pass
237
+ pom_tmp_path = None
238
+ else:
239
+ logger.debug(f"{rel_path}: Central ({central_oss_name} {c_version}) differs from JAR pom ({jar_oss_name} {v2})")
240
+ groupId, artifactId, version = c_groupId, c_artifactId, c_version
241
+ source = 'Maven Central'
242
+ confirmed_in_central = True
243
+
244
+ tmp_path, timed_out = _download_pom_to_tempfile(
245
+ groupId, artifactId, version, timeout=search_timeout)
246
+ if timed_out:
247
+ logger.debug(f"{rel_path}: POM download timed out – will retry")
248
+ if pom_tmp_path:
249
+ try:
250
+ os.remove(pom_tmp_path)
251
+ except Exception:
252
+ pass
253
+ return None, True
254
+ if tmp_path:
255
+ try:
256
+ license_str = get_license_from_pom(
257
+ group_id=groupId, artifact_id=artifactId, version=version,
258
+ pom_path=tmp_path, check_parent=True)
259
+ logger.debug(f"{rel_path}: license from Central POM={license_str!r}")
260
+ except Exception as ex:
261
+ logger.debug(f"get_license_from_pom (Central pom_path) failed: {ex}")
262
+ finally:
263
+ try:
264
+ os.remove(tmp_path)
265
+ except Exception:
266
+ pass
267
+
268
+ if pom_tmp_path:
269
+ try:
270
+ os.remove(pom_tmp_path)
271
+ except Exception:
272
+ pass
273
+
274
+ else:
275
+ logger.debug(f"{rel_path}: not found in Maven Central – falling back to JAR internals")
276
+
277
+ if g2 or a2:
278
+ groupId, artifactId, version, project_url = g2, a2, v2, url2
279
+ source = 'pom.xml'
280
+
281
+ if pom_tmp_path:
282
+ try:
283
+ if not license_str:
284
+ license_str = get_license_from_pom(
285
+ group_id=groupId, artifact_id=artifactId, version=version,
286
+ pom_path=pom_tmp_path, check_parent=True)
287
+ logger.debug(f"{rel_path}: license from JAR pom.xml={license_str!r}")
288
+ except Exception as ex:
289
+ logger.debug(f"get_license_from_pom (jar pom_path) failed: {ex}")
290
+ finally:
291
+ try:
292
+ os.remove(pom_tmp_path)
293
+ except Exception:
294
+ pass
295
+ if not confirmed_in_central and not skip_central:
296
+ confirmed_in_central = _exists_in_central(groupId, artifactId, version)
297
+
298
+ if not (groupId and artifactId):
299
+ g3, a3, v3, url3 = _read_manifest_from_jar(jar_path)
300
+ if g3 or a3:
301
+ groupId = g3
302
+ artifactId = a3
303
+ version = version or v3
304
+ project_url = project_url or url3
305
+ source = 'MANIFEST.MF'
306
+
307
+ if not (groupId or artifactId):
308
+ return None, False
309
+
310
+ oss_name = f"{groupId}:{artifactId}" if groupId and artifactId else (artifactId or groupId)
311
+ dl_url = _build_central_jar_url(groupId, artifactId, version) if confirmed_in_central else ""
312
+
313
+ oss = OssItem(oss_name, version, license_str, dl_url)
314
+ oss.comment = source
315
+
316
+ logger.debug(
317
+ f"Result: {rel_path} | {oss_name} {version} | [{license_str}] | dl={dl_url} | source={source}")
318
+
319
+ return {"oss_list": [oss], "sha1": sha1}, False
320
+
321
+
322
+ def analyze_jar_file(path_to_find_bin, path_to_exclude):
323
+ global _central_network_warned
324
+ _central_network_warned = False
325
+ jar_items = {}
326
+ success = True
327
+ retry_queue = []
328
+
329
+ jar_files = []
330
+ for root_dir, _dirs, files in os.walk(path_to_find_bin):
331
+ for fname in files:
332
+ if fname.endswith('.jar'):
333
+ jar_files.append(os.path.join(root_dir, fname))
334
+
335
+ if not jar_files:
336
+ logger.info("No .jar files found – skipping JAR OSS analysis.")
337
+ return jar_items, success
338
+
339
+ for jar_path in jar_files:
340
+ rel_path = os.path.relpath(jar_path, path_to_find_bin)
341
+ if rel_path in path_to_exclude:
342
+ continue
343
+
344
+ sha1 = _sha1_of_file(jar_path)
345
+ result, needs_retry = _process_one_jar(
346
+ jar_path, rel_path, sha1, search_timeout=_CENTRAL_SEARCH_TIMEOUT)
347
+
348
+ if needs_retry:
349
+ logger.debug(f"{rel_path}: Central API timed out – queued for retry (attempt 1/{_MAX_RETRY})")
350
+ retry_queue.append((jar_path, rel_path, sha1, 1))
351
+ elif result is not None:
352
+ jar_items[rel_path] = result
353
+
354
+ while retry_queue:
355
+ next_queue = []
356
+ for jar_path, rel_path, sha1, attempt in retry_queue:
357
+ if attempt >= _MAX_RETRY:
358
+ logger.warning(
359
+ f"{rel_path}: Maven Central API timed out after {_MAX_RETRY} attempts"
360
+ " – falling back to JAR internals")
361
+ result, _ = _process_one_jar(jar_path, rel_path, sha1, skip_central=True)
362
+ if result is not None:
363
+ jar_items[rel_path] = result
364
+ continue
365
+
366
+ logger.debug(f"{rel_path}: retrying Central API (attempt {attempt + 1}/{_MAX_RETRY})")
367
+ result, needs_retry = _process_one_jar(
368
+ jar_path, rel_path, sha1, search_timeout=_CENTRAL_SEARCH_TIMEOUT)
369
+
370
+ if needs_retry:
371
+ next_queue.append((jar_path, rel_path, sha1, attempt + 1))
372
+ elif result is not None:
373
+ jar_items[rel_path] = result
374
+
375
+ retry_queue = next_queue
376
+
377
+ return jar_items, success
378
+
379
+
380
+ def merge_binary_list(jar_items, bin_list):
381
+ not_found_bin = []
382
+
383
+ for key, value in jar_items.items():
384
+ found = False
385
+ oss_list = value["oss_list"]
386
+ sha1 = value.get("sha1", "")
387
+ for bin in bin_list:
388
+ if bin.source_name_or_path == key:
389
+ found = True
390
+ for oss in oss_list:
391
+ if oss.name and oss.license:
392
+ bin.found_in_jar_analysis = True
393
+ break
394
+ bin.set_oss_items(oss_list)
395
+ else:
396
+ if bin.checksum == sha1:
397
+ bin.set_oss_items(oss_list)
398
+
399
+ if not found:
400
+ bin_item = BinaryItem(os.path.abspath(key))
401
+ bin_item.binary_name_without_path = os.path.basename(key)
402
+ bin_item.source_name_or_path = key
403
+ bin_item.set_oss_items(oss_list)
404
+ not_found_bin.append(bin_item)
405
+
406
+ bin_list += not_found_bin
407
+ return bin_list
@@ -44,7 +44,7 @@ BYTES = 2048
44
44
  BIN_EXT_HEADER = {'BIN_FL_Binary': ['ID', 'Binary Path', 'OSS Name',
45
45
  'OSS Version', 'License', 'Download Location',
46
46
  'Homepage', 'Copyright Text', 'Exclude',
47
- 'Comment', 'Vulnerability Link', 'TLSH', 'SHA1']}
47
+ 'Comment', 'TLSH', 'SHA1']}
48
48
  HIDE_HEADER = {'TLSH', "SHA1"}
49
49
 
50
50
 
@@ -118,7 +118,7 @@ def init(path_to_find_bin, output_file_name, formats, path_to_exclude=[]):
118
118
  if len(output_extensions) < 1:
119
119
  sys.exit(0)
120
120
 
121
- combined_paths_and_files = [os.path.join(original_output_path, file) for file in output_files]
121
+ combined_paths_and_files = [os.path.join(output_path, file) for file in output_files]
122
122
  else:
123
123
  logger.error(f"Format error - {msg}")
124
124
  sys.exit(1)
@@ -233,21 +233,14 @@ def find_binaries(path_to_find_bin, output_dir, formats, dburl="", simple_mode=F
233
233
  scan_item = ScannerItem(PKG_NAME, start_time)
234
234
  scan_item.set_cover_pathinfo(path_to_find_bin, excluded_path_without_dot)
235
235
  try:
236
- # Run OWASP Dependency-check
236
+ # Run JAR analysis via Maven Central API
237
237
  if found_jar:
238
- # Check Java version (Dependency-check requires Java 11+)
239
- java_ver = get_java_version()
240
- if java_ver is None:
241
- logger.warning("Java runtime not found. FOSSLight Binary Scanner requires Java 11+ to analyze .jar files.")
242
- elif java_ver < 11:
243
- logger.warning(f"Java version {java_ver} detected (<11). FOSSLight Binary Scanner requires Java 11+ to analyze .jar files.")
238
+ logger.info("Run to analyze .jar file")
239
+ jar_items, success = analyze_jar_file(path_to_find_bin, excluded_files)
240
+ if success:
241
+ return_list = merge_binary_list(jar_items, return_list)
244
242
  else:
245
- logger.info("Run OWASP Dependency-check to analyze .jar file")
246
- owasp_items, vulnerability_items, success = analyze_jar_file(path_to_find_bin, excluded_files)
247
- if success:
248
- return_list = merge_binary_list(owasp_items, vulnerability_items, return_list)
249
- else:
250
- logger.warning("Could not find OSS information for some jar files.")
243
+ logger.warning("Could not find OSS information for some jar files.")
251
244
 
252
245
  return_list, db_loaded_cnt = get_oss_info_from_db(return_list, dburl)
253
246
  return_list = sorted(return_list, key=lambda row: (row.bin_name_with_path))
@@ -281,13 +274,19 @@ def find_binaries(path_to_find_bin, output_dir, formats, dburl="", simple_mode=F
281
274
  logger.error(f"Fail to generate result file.:{writing_msg}")
282
275
 
283
276
  try:
284
- move_log_file(log_file, os.path.join(original_output_path, f"fosslight_log_bin_{start_time}.txt"))
277
+ if os.path.isfile(log_file):
278
+ move_log_file(log_file, os.path.join(original_output_path, f"fosslight_log_bin_{start_time}.txt"))
279
+ else:
280
+ logger.debug("Moving binary analysis log file is skipped")
285
281
  except Exception as ex:
286
282
  logger.debug(f"Failed to move log file: {ex}")
287
283
 
288
284
  try:
289
- shutil.copytree(output_path, original_output_path, dirs_exist_ok=True)
290
- shutil.rmtree(output_path)
285
+ if os.path.isdir(output_path):
286
+ shutil.copytree(output_path, original_output_path, dirs_exist_ok=True)
287
+ shutil.rmtree(output_path)
288
+ else:
289
+ logger.debug(f"Temp directory not found, skip moving: {output_path}")
291
290
  except Exception as ex:
292
291
  logger.debug(f"Failed to move temp files: {ex}")
293
292
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fosslight_binary
3
- Version: 5.1.24
3
+ Version: 5.1.26
4
4
  Summary: FOSSLight Binary Scanner
5
5
  Author: LG Electronics
6
6
  License-Expression: Apache-2.0
@@ -20,6 +20,7 @@ License-File: LICENSES/Apache-2.0.txt
20
20
  License-File: LICENSES/LicenseRef-3rd_party_licenses.txt
21
21
  Requires-Dist: binaryornot==0.4.4
22
22
  Requires-Dist: chardet<5.0.0
23
+ Requires-Dist: defusedxml
23
24
  Requires-Dist: numpy
24
25
  Requires-Dist: pandas
25
26
  Requires-Dist: parmap
@@ -0,0 +1,22 @@
1
+ LICENSE
2
+ MANIFEST.in
3
+ README.md
4
+ pyproject.toml
5
+ setup.cfg
6
+ LICENSES/Apache-2.0.txt
7
+ LICENSES/LicenseRef-3rd_party_licenses.txt
8
+ src/fosslight_binary/__init__.py
9
+ src/fosslight_binary/_binary.py
10
+ src/fosslight_binary/_binary_dao.py
11
+ src/fosslight_binary/_help.py
12
+ src/fosslight_binary/_jar_analysis.py
13
+ src/fosslight_binary/_simple_mode.py
14
+ src/fosslight_binary/binary_analysis.py
15
+ src/fosslight_binary/cli.py
16
+ src/fosslight_binary.egg-info/PKG-INFO
17
+ src/fosslight_binary.egg-info/SOURCES.txt
18
+ src/fosslight_binary.egg-info/dependency_links.txt
19
+ src/fosslight_binary.egg-info/entry_points.txt
20
+ src/fosslight_binary.egg-info/requires.txt
21
+ src/fosslight_binary.egg-info/top_level.txt
22
+ tests/test_fosslight_binary.py
@@ -1,5 +1,6 @@
1
1
  binaryornot==0.4.4
2
2
  chardet<5.0.0
3
+ defusedxml
3
4
  numpy
4
5
  pandas
5
6
  parmap