fosslight-binary 5.1.23__tar.gz → 5.1.25__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.23 → fosslight_binary-5.1.25}/PKG-INFO +3 -2
  2. {fosslight_binary-5.1.23 → fosslight_binary-5.1.25}/pyproject.toml +4 -9
  3. fosslight_binary-5.1.25/src/fosslight_binary/__init__.py +4 -0
  4. {fosslight_binary-5.1.23 → fosslight_binary-5.1.25}/src/fosslight_binary/_binary.py +3 -27
  5. {fosslight_binary-5.1.23 → fosslight_binary-5.1.25}/src/fosslight_binary/_binary_dao.py +2 -2
  6. {fosslight_binary-5.1.23 → fosslight_binary-5.1.25}/src/fosslight_binary/_help.py +6 -10
  7. fosslight_binary-5.1.25/src/fosslight_binary/_jar_analysis.py +407 -0
  8. {fosslight_binary-5.1.23 → fosslight_binary-5.1.25}/src/fosslight_binary/binary_analysis.py +15 -21
  9. {fosslight_binary-5.1.23 → fosslight_binary-5.1.25}/src/fosslight_binary/cli.py +1 -1
  10. {fosslight_binary-5.1.23 → fosslight_binary-5.1.25}/src/fosslight_binary.egg-info/PKG-INFO +3 -2
  11. fosslight_binary-5.1.25/src/fosslight_binary.egg-info/SOURCES.txt +22 -0
  12. {fosslight_binary-5.1.23 → fosslight_binary-5.1.25}/src/fosslight_binary.egg-info/requires.txt +2 -1
  13. fosslight_binary-5.1.23/src/fosslight_binary/__init__.py +0 -79
  14. fosslight_binary-5.1.23/src/fosslight_binary/_jar_analysis.py +0 -311
  15. fosslight_binary-5.1.23/src/fosslight_binary/third_party/dependency-check/LICENSE.txt +0 -202
  16. fosslight_binary-5.1.23/src/fosslight_binary/third_party/dependency-check/NOTICE.txt +0 -18
  17. fosslight_binary-5.1.23/src/fosslight_binary/third_party/dependency-check/README.md +0 -20
  18. fosslight_binary-5.1.23/src/fosslight_binary/third_party/dependency-check/bin/completion-for-dependency-check.sh +0 -150
  19. fosslight_binary-5.1.23/src/fosslight_binary/third_party/dependency-check/bin/dependency-check.bat +0 -110
  20. fosslight_binary-5.1.23/src/fosslight_binary/third_party/dependency-check/bin/dependency-check.sh +0 -135
  21. fosslight_binary-5.1.23/src/fosslight_binary/third_party/dependency-check/lib/aho-corasick-double-array-trie-1.2.3.jar +0 -0
  22. fosslight_binary-5.1.23/src/fosslight_binary/third_party/dependency-check/lib/android-json-0.0.20131108.vaadin1.jar +0 -0
  23. fosslight_binary-5.1.23/src/fosslight_binary/third_party/dependency-check/lib/annotations-26.0.2-1.jar +0 -0
  24. fosslight_binary-5.1.23/src/fosslight_binary/third_party/dependency-check/lib/ant-1.10.15.jar +0 -0
  25. fosslight_binary-5.1.23/src/fosslight_binary/third_party/dependency-check/lib/bcpg-jdk18on-1.78.jar +0 -0
  26. fosslight_binary-5.1.23/src/fosslight_binary/third_party/dependency-check/lib/bcprov-jdk18on-1.78.jar +0 -0
  27. fosslight_binary-5.1.23/src/fosslight_binary/third_party/dependency-check/lib/commons-cli-1.10.0.jar +0 -0
  28. fosslight_binary-5.1.23/src/fosslight_binary/third_party/dependency-check/lib/commons-codec-1.19.0.jar +0 -0
  29. fosslight_binary-5.1.23/src/fosslight_binary/third_party/dependency-check/lib/commons-collections-3.2.2.jar +0 -0
  30. fosslight_binary-5.1.23/src/fosslight_binary/third_party/dependency-check/lib/commons-collections4-4.5.0.jar +0 -0
  31. fosslight_binary-5.1.23/src/fosslight_binary/third_party/dependency-check/lib/commons-compress-1.27.1.jar +0 -0
  32. fosslight_binary-5.1.23/src/fosslight_binary/third_party/dependency-check/lib/commons-dbcp2-2.13.0.jar +0 -0
  33. fosslight_binary-5.1.23/src/fosslight_binary/third_party/dependency-check/lib/commons-digester-2.1.jar +0 -0
  34. fosslight_binary-5.1.23/src/fosslight_binary/third_party/dependency-check/lib/commons-io-2.20.0.jar +0 -0
  35. fosslight_binary-5.1.23/src/fosslight_binary/third_party/dependency-check/lib/commons-jcs3-core-3.2.1.jar +0 -0
  36. fosslight_binary-5.1.23/src/fosslight_binary/third_party/dependency-check/lib/commons-lang3-3.19.0.jar +0 -0
  37. fosslight_binary-5.1.23/src/fosslight_binary/third_party/dependency-check/lib/commons-logging-1.3.4.jar +0 -0
  38. fosslight_binary-5.1.23/src/fosslight_binary/third_party/dependency-check/lib/commons-pool2-2.12.0.jar +0 -0
  39. fosslight_binary-5.1.23/src/fosslight_binary/third_party/dependency-check/lib/commons-text-1.14.0.jar +0 -0
  40. fosslight_binary-5.1.23/src/fosslight_binary/third_party/dependency-check/lib/commons-validator-1.10.0.jar +0 -0
  41. fosslight_binary-5.1.23/src/fosslight_binary/third_party/dependency-check/lib/compiler-0.9.6.jar +0 -0
  42. fosslight_binary-5.1.23/src/fosslight_binary/third_party/dependency-check/lib/cpe-parser-3.0.0.jar +0 -0
  43. fosslight_binary-5.1.23/src/fosslight_binary/third_party/dependency-check/lib/dependency-check-cli-12.1.7.jar +0 -0
  44. fosslight_binary-5.1.23/src/fosslight_binary/third_party/dependency-check/lib/dependency-check-core-12.1.7.jar +0 -0
  45. fosslight_binary-5.1.23/src/fosslight_binary/third_party/dependency-check/lib/dependency-check-utils-12.1.7.jar +0 -0
  46. fosslight_binary-5.1.23/src/fosslight_binary/third_party/dependency-check/lib/error_prone_annotations-2.41.0.jar +0 -0
  47. fosslight_binary-5.1.23/src/fosslight_binary/third_party/dependency-check/lib/failureaccess-1.0.3.jar +0 -0
  48. fosslight_binary-5.1.23/src/fosslight_binary/third_party/dependency-check/lib/gson-2.9.0.jar +0 -0
  49. fosslight_binary-5.1.23/src/fosslight_binary/third_party/dependency-check/lib/guava-33.5.0-jre.jar +0 -0
  50. fosslight_binary-5.1.23/src/fosslight_binary/third_party/dependency-check/lib/h2-2.3.232.jar +0 -0
  51. fosslight_binary-5.1.23/src/fosslight_binary/third_party/dependency-check/lib/httpclient5-5.5.jar +0 -0
  52. fosslight_binary-5.1.23/src/fosslight_binary/third_party/dependency-check/lib/httpclient5-cache-5.4.3.jar +0 -0
  53. fosslight_binary-5.1.23/src/fosslight_binary/third_party/dependency-check/lib/httpcore5-5.3.6.jar +0 -0
  54. fosslight_binary-5.1.23/src/fosslight_binary/third_party/dependency-check/lib/httpcore5-h2-5.3.4.jar +0 -0
  55. fosslight_binary-5.1.23/src/fosslight_binary/third_party/dependency-check/lib/j2objc-annotations-3.1.jar +0 -0
  56. fosslight_binary-5.1.23/src/fosslight_binary/third_party/dependency-check/lib/jackson-annotations-2.20.jar +0 -0
  57. fosslight_binary-5.1.23/src/fosslight_binary/third_party/dependency-check/lib/jackson-core-2.20.0.jar +0 -0
  58. fosslight_binary-5.1.23/src/fosslight_binary/third_party/dependency-check/lib/jackson-databind-2.20.0.jar +0 -0
  59. fosslight_binary-5.1.23/src/fosslight_binary/third_party/dependency-check/lib/jackson-dataformat-yaml-2.20.0.jar +0 -0
  60. fosslight_binary-5.1.23/src/fosslight_binary/third_party/dependency-check/lib/jackson-datatype-jsr310-2.20.0.jar +0 -0
  61. fosslight_binary-5.1.23/src/fosslight_binary/third_party/dependency-check/lib/jackson-module-blackbird-2.20.0.jar +0 -0
  62. fosslight_binary-5.1.23/src/fosslight_binary/third_party/dependency-check/lib/jakarta.json-2.0.1.jar +0 -0
  63. fosslight_binary-5.1.23/src/fosslight_binary/third_party/dependency-check/lib/jakarta.transaction-api-1.3.3.jar +0 -0
  64. fosslight_binary-5.1.23/src/fosslight_binary/third_party/dependency-check/lib/javax.activation-api-1.2.0.jar +0 -0
  65. fosslight_binary-5.1.23/src/fosslight_binary/third_party/dependency-check/lib/javax.inject-1.jar +0 -0
  66. fosslight_binary-5.1.23/src/fosslight_binary/third_party/dependency-check/lib/javax.ws.rs-api-2.0.1.jar +0 -0
  67. fosslight_binary-5.1.23/src/fosslight_binary/third_party/dependency-check/lib/jaxb-api-2.3.1.jar +0 -0
  68. fosslight_binary-5.1.23/src/fosslight_binary/third_party/dependency-check/lib/jcs3-slf4j-1.0.5.jar +0 -0
  69. fosslight_binary-5.1.23/src/fosslight_binary/third_party/dependency-check/lib/jdiagnostics-1.0.7.jar +0 -0
  70. fosslight_binary-5.1.23/src/fosslight_binary/third_party/dependency-check/lib/jmustache-1.16.jar +0 -0
  71. fosslight_binary-5.1.23/src/fosslight_binary/third_party/dependency-check/lib/joda-time-2.14.0.jar +0 -0
  72. fosslight_binary-5.1.23/src/fosslight_binary/third_party/dependency-check/lib/jsoup-1.21.2.jar +0 -0
  73. fosslight_binary-5.1.23/src/fosslight_binary/third_party/dependency-check/lib/jspecify-1.0.0.jar +0 -0
  74. fosslight_binary-5.1.23/src/fosslight_binary/third_party/dependency-check/lib/jsr305-3.0.2.jar +0 -0
  75. fosslight_binary-5.1.23/src/fosslight_binary/third_party/dependency-check/lib/jul-to-slf4j-1.7.36.jar +0 -0
  76. fosslight_binary-5.1.23/src/fosslight_binary/third_party/dependency-check/lib/listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar +0 -0
  77. fosslight_binary-5.1.23/src/fosslight_binary/third_party/dependency-check/lib/logback-classic-1.2.13.jar +0 -0
  78. fosslight_binary-5.1.23/src/fosslight_binary/third_party/dependency-check/lib/logback-core-1.2.13.jar +0 -0
  79. fosslight_binary-5.1.23/src/fosslight_binary/third_party/dependency-check/lib/lucene-analysis-common-9.12.0.jar +0 -0
  80. fosslight_binary-5.1.23/src/fosslight_binary/third_party/dependency-check/lib/lucene-core-9.12.0.jar +0 -0
  81. fosslight_binary-5.1.23/src/fosslight_binary/third_party/dependency-check/lib/lucene-facet-9.12.0.jar +0 -0
  82. fosslight_binary-5.1.23/src/fosslight_binary/third_party/dependency-check/lib/lucene-queries-9.12.0.jar +0 -0
  83. fosslight_binary-5.1.23/src/fosslight_binary/third_party/dependency-check/lib/lucene-queryparser-9.12.0.jar +0 -0
  84. fosslight_binary-5.1.23/src/fosslight_binary/third_party/dependency-check/lib/lucene-sandbox-9.12.0.jar +0 -0
  85. fosslight_binary-5.1.23/src/fosslight_binary/third_party/dependency-check/lib/minlog-1.3.1.jar +0 -0
  86. fosslight_binary-5.1.23/src/fosslight_binary/third_party/dependency-check/lib/open-vulnerability-clients-7.3.2.jar +0 -0
  87. fosslight_binary-5.1.23/src/fosslight_binary/third_party/dependency-check/lib/ossindex-service-api-1.8.2.jar +0 -0
  88. fosslight_binary-5.1.23/src/fosslight_binary/third_party/dependency-check/lib/ossindex-service-client-1.8.2.jar +0 -0
  89. fosslight_binary-5.1.23/src/fosslight_binary/third_party/dependency-check/lib/package-url-java-1.2.0.jar +0 -0
  90. fosslight_binary-5.1.23/src/fosslight_binary/third_party/dependency-check/lib/packager-core-0.21.0.jar +0 -0
  91. fosslight_binary-5.1.23/src/fosslight_binary/third_party/dependency-check/lib/packager-rpm-0.21.0.jar +0 -0
  92. fosslight_binary-5.1.23/src/fosslight_binary/third_party/dependency-check/lib/packageurl-java-1.5.0.jar +0 -0
  93. fosslight_binary-5.1.23/src/fosslight_binary/third_party/dependency-check/lib/pecoff4j-0.0.2.1.jar +0 -0
  94. fosslight_binary-5.1.23/src/fosslight_binary/third_party/dependency-check/lib/retirejs-core-3.0.4.jar +0 -0
  95. fosslight_binary-5.1.23/src/fosslight_binary/third_party/dependency-check/lib/semver4j-5.8.0.jar +0 -0
  96. fosslight_binary-5.1.23/src/fosslight_binary/third_party/dependency-check/lib/slf4j-api-1.7.36.jar +0 -0
  97. fosslight_binary-5.1.23/src/fosslight_binary/third_party/dependency-check/lib/snakeyaml-2.4.jar +0 -0
  98. fosslight_binary-5.1.23/src/fosslight_binary/third_party/dependency-check/lib/spotbugs-annotations-4.9.6.jar +0 -0
  99. fosslight_binary-5.1.23/src/fosslight_binary/third_party/dependency-check/lib/toml4j-0.7.2.jar +0 -0
  100. fosslight_binary-5.1.23/src/fosslight_binary/third_party/dependency-check/lib/velocity-engine-core-2.4.1.jar +0 -0
  101. fosslight_binary-5.1.23/src/fosslight_binary/third_party/dependency-check/lib/xz-1.9.jar +0 -0
  102. fosslight_binary-5.1.23/src/fosslight_binary.egg-info/SOURCES.txt +0 -109
  103. {fosslight_binary-5.1.23 → fosslight_binary-5.1.25}/LICENSE +0 -0
  104. {fosslight_binary-5.1.23 → fosslight_binary-5.1.25}/LICENSES/Apache-2.0.txt +0 -0
  105. {fosslight_binary-5.1.23 → fosslight_binary-5.1.25}/LICENSES/LicenseRef-3rd_party_licenses.txt +0 -0
  106. {fosslight_binary-5.1.23 → fosslight_binary-5.1.25}/MANIFEST.in +0 -0
  107. {fosslight_binary-5.1.23 → fosslight_binary-5.1.25}/README.md +0 -0
  108. {fosslight_binary-5.1.23 → fosslight_binary-5.1.25}/setup.cfg +0 -0
  109. {fosslight_binary-5.1.23 → fosslight_binary-5.1.25}/src/fosslight_binary/_simple_mode.py +0 -0
  110. {fosslight_binary-5.1.23 → fosslight_binary-5.1.25}/src/fosslight_binary.egg-info/dependency_links.txt +0 -0
  111. {fosslight_binary-5.1.23 → fosslight_binary-5.1.25}/src/fosslight_binary.egg-info/entry_points.txt +0 -0
  112. {fosslight_binary-5.1.23 → fosslight_binary-5.1.25}/src/fosslight_binary.egg-info/top_level.txt +0 -0
  113. {fosslight_binary-5.1.23 → fosslight_binary-5.1.25}/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.23
3
+ Version: 5.1.25
4
4
  Summary: FOSSLight Binary Scanner
5
5
  Author: LG Electronics
6
6
  License-Expression: Apache-2.0
@@ -18,8 +18,9 @@ Description-Content-Type: text/markdown
18
18
  License-File: LICENSE
19
19
  License-File: LICENSES/Apache-2.0.txt
20
20
  License-File: LICENSES/LicenseRef-3rd_party_licenses.txt
21
- Requires-Dist: binaryornot
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.23"
10
+ version = "5.1.25"
11
11
  description = "FOSSLight Binary Scanner"
12
12
  readme = "README.md"
13
13
  license = "Apache-2.0"
@@ -25,8 +25,9 @@ classifiers = [
25
25
  ]
26
26
  requires-python = ">=3.10,<3.15"
27
27
  dependencies = [
28
- "binaryornot",
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:
@@ -8,7 +8,7 @@ from fosslight_util.output_format import SUPPORT_FORMAT
8
8
  _HELP_MESSAGE_BINARY = f"""
9
9
  📖 Usage
10
10
  ────────────────────────────────────────────────────────────────────
11
- fosslight_bin [options] <arguments>
11
+ fosslight_binary [options] <arguments>
12
12
 
13
13
  📝 Description
14
14
  ────────────────────────────────────────────────────────────────────
@@ -26,13 +26,12 @@ _HELP_MESSAGE_BINARY = f"""
26
26
  (multiple formats can be specified, separated by space)
27
27
  -e <pattern> Exclude paths from analysis (files and directories)
28
28
  ⚠️ IMPORTANT: Always wrap in quotes to avoid shell expansion
29
- Example: fosslight_bin -e "test/" "*.jar"
29
+ Example: fosslight_binary -e "test/" "*.jar"
30
30
  -h Show this help message
31
31
  -v Show version information
32
32
 
33
33
  🔍 Scanner-Specific Options
34
34
  ────────────────────────────────────────────────────────────────────
35
- -s Extract only the binary list in simple mode
36
35
  -d <db_url> DB Connection (format: 'postgresql://user:pass@host:port/db')
37
36
  --notice Print the open source license notice text
38
37
  --no_correction Skip OSS information correction with sbom-info.yaml
@@ -41,19 +40,16 @@ _HELP_MESSAGE_BINARY = f"""
41
40
  💡 Examples
42
41
  ────────────────────────────────────────────────────────────────────
43
42
  # Scan current directory
44
- fosslight_bin
43
+ fosslight_binary
45
44
 
46
45
  # Scan specific path with exclusions
47
- fosslight_bin -p /path/to/binaries -e "test/" "*.so"
46
+ fosslight_binary -p /path/to/binaries -e "test/" "*.so"
48
47
 
49
48
  # Generate output in specific format
50
- fosslight_bin -f excel -o results/
51
-
52
- # Simple mode (extract binary list only)
53
- fosslight_bin -s -o binary_list.txt
49
+ fosslight_binary -f excel -o results/
54
50
 
55
51
  # Connect to Binary DB for OSS information
56
- fosslight_bin -d "postgresql://user:pass@localhost:5432/exampledb"
52
+ fosslight_binary -d "postgresql://user:pass@localhost:5432/exampledb"
57
53
  """
58
54
 
59
55
 
@@ -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