fosslight-binary 5.1.8__tar.gz → 5.1.10__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 (27) hide show
  1. {fosslight_binary-5.1.8 → fosslight_binary-5.1.10}/PKG-INFO +1 -2
  2. {fosslight_binary-5.1.8 → fosslight_binary-5.1.10}/requirements.txt +0 -1
  3. {fosslight_binary-5.1.8 → fosslight_binary-5.1.10}/setup.py +1 -1
  4. fosslight_binary-5.1.10/src/fosslight_binary/__init__.py +149 -0
  5. {fosslight_binary-5.1.8 → fosslight_binary-5.1.10}/src/fosslight_binary/_binary.py +18 -5
  6. {fosslight_binary-5.1.8 → fosslight_binary-5.1.10}/src/fosslight_binary/_binary_dao.py +60 -38
  7. {fosslight_binary-5.1.8 → fosslight_binary-5.1.10}/src/fosslight_binary/_jar_analysis.py +84 -40
  8. {fosslight_binary-5.1.8 → fosslight_binary-5.1.10}/src/fosslight_binary/binary_analysis.py +10 -3
  9. {fosslight_binary-5.1.8 → fosslight_binary-5.1.10}/src/fosslight_binary.egg-info/PKG-INFO +1 -2
  10. {fosslight_binary-5.1.8 → fosslight_binary-5.1.10}/src/fosslight_binary.egg-info/requires.txt +0 -1
  11. fosslight_binary-5.1.8/src/fosslight_binary/__init__.py +0 -0
  12. {fosslight_binary-5.1.8 → fosslight_binary-5.1.10}/LICENSE +0 -0
  13. {fosslight_binary-5.1.8 → fosslight_binary-5.1.10}/LICENSES/Apache-2.0.txt +0 -0
  14. {fosslight_binary-5.1.8 → fosslight_binary-5.1.10}/LICENSES/LicenseRef-3rd_party_licenses.txt +0 -0
  15. {fosslight_binary-5.1.8 → fosslight_binary-5.1.10}/MANIFEST.in +0 -0
  16. {fosslight_binary-5.1.8 → fosslight_binary-5.1.10}/README.md +0 -0
  17. {fosslight_binary-5.1.8 → fosslight_binary-5.1.10}/setup.cfg +0 -0
  18. {fosslight_binary-5.1.8 → fosslight_binary-5.1.10}/src/fosslight_binary/LICENSES/LICENSE +0 -0
  19. {fosslight_binary-5.1.8 → fosslight_binary-5.1.10}/src/fosslight_binary/LICENSES/LicenseRef-3rd_party_licenses.txt +0 -0
  20. {fosslight_binary-5.1.8 → fosslight_binary-5.1.10}/src/fosslight_binary/_help.py +0 -0
  21. {fosslight_binary-5.1.8 → fosslight_binary-5.1.10}/src/fosslight_binary/_simple_mode.py +0 -0
  22. {fosslight_binary-5.1.8 → fosslight_binary-5.1.10}/src/fosslight_binary/cli.py +0 -0
  23. {fosslight_binary-5.1.8 → fosslight_binary-5.1.10}/src/fosslight_binary.egg-info/SOURCES.txt +0 -0
  24. {fosslight_binary-5.1.8 → fosslight_binary-5.1.10}/src/fosslight_binary.egg-info/dependency_links.txt +0 -0
  25. {fosslight_binary-5.1.8 → fosslight_binary-5.1.10}/src/fosslight_binary.egg-info/entry_points.txt +0 -0
  26. {fosslight_binary-5.1.8 → fosslight_binary-5.1.10}/src/fosslight_binary.egg-info/top_level.txt +0 -0
  27. {fosslight_binary-5.1.8 → fosslight_binary-5.1.10}/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.8
3
+ Version: 5.1.10
4
4
  Summary: FOSSLight Binary Scanner
5
5
  Home-page: https://github.com/fosslight/fosslight_binary_scanner
6
6
  Download-URL: https://github.com/fosslight/fosslight_binary_scanner
@@ -27,7 +27,6 @@ Requires-Dist: pytz
27
27
  Requires-Dist: XlsxWriter
28
28
  Requires-Dist: PyYAML
29
29
  Requires-Dist: fosslight_util>=2.1.13
30
- Requires-Dist: dependency-check
31
30
  Requires-Dist: python-magic-bin; sys_platform == "win32"
32
31
  Requires-Dist: python-magic; "darwin" in sys_platform
33
32
  Requires-Dist: python-magic; "linux" in sys_platform
@@ -9,4 +9,3 @@ pytz
9
9
  XlsxWriter
10
10
  PyYAML
11
11
  fosslight_util>=2.1.13
12
- dependency-check
@@ -33,7 +33,7 @@ if __name__ == "__main__":
33
33
 
34
34
  setup(
35
35
  name=_PACKAEG_NAME,
36
- version='5.1.8',
36
+ version='5.1.10',
37
37
  package_dir={"": "src"},
38
38
  packages=find_packages(where='src'),
39
39
  description='FOSSLight Binary Scanner',
@@ -0,0 +1,149 @@
1
+ #!/usr/bin/env python
2
+ # -*- coding: utf-8 -*-
3
+ # Copyright (c) 2025 LG Electronics Inc.
4
+ # SPDX-License-Identifier: Apache-2.0
5
+ import logging
6
+ import os
7
+ import stat
8
+ import subprocess
9
+ import tempfile
10
+ import urllib.request
11
+ import zipfile
12
+ import sys
13
+
14
+ logger = logging.getLogger(__name__)
15
+ DEPENDENCY_CHECK_VERSION = "12.1.7"
16
+
17
+
18
+ def _install_dependency_check():
19
+ """Install OWASP dependency-check"""
20
+ try:
21
+ # Skip if explicitly disabled
22
+ if os.environ.get('FOSSLIGHT_SKIP_AUTO_INSTALL', '').lower() in ('1', 'true', 'yes'):
23
+ logger.info("Auto-install disabled by environment variable")
24
+ return
25
+
26
+ env_home = os.environ.get('DEPENDENCY_CHECK_HOME', '').strip()
27
+ install_dir = None
28
+ forced_env = False
29
+ if env_home:
30
+ # Normalize
31
+ env_home_abs = os.path.abspath(env_home)
32
+ # Detect if env_home already the actual extracted root (ends with dependency-check)
33
+ candidate_bin_win = os.path.join(env_home_abs, 'bin', 'dependency-check.bat')
34
+ candidate_bin_nix = os.path.join(env_home_abs, 'bin', 'dependency-check.sh')
35
+ if os.path.exists(candidate_bin_win) or os.path.exists(candidate_bin_nix):
36
+ # env points directly to dependency-check root; install_dir is its parent
37
+ install_dir = os.path.dirname(env_home_abs)
38
+ forced_env = True
39
+ else:
40
+ # Assume env_home is the base directory where we should extract dependency-check/
41
+ install_dir = env_home_abs
42
+
43
+ if not install_dir:
44
+ # Fallback hierarchy: executable dir (if frozen) -> CWD
45
+ candidate_base = None
46
+ if getattr(sys, 'frozen', False):
47
+ exe_dir = os.path.dirname(os.path.abspath(sys.executable))
48
+ candidate_base = os.path.join(exe_dir, 'fosslight_dc_bin')
49
+
50
+ if not os.access(exe_dir, os.W_OK):
51
+ candidate_base = None
52
+ else:
53
+ logger.debug(f"Using executable directory base: {candidate_base}")
54
+ if not candidate_base:
55
+ candidate_base = os.path.abspath(os.path.join(os.getcwd(), 'fosslight_dc_bin'))
56
+ install_dir = candidate_base
57
+ else:
58
+ logger.debug(f"Resolved install_dir: {install_dir}")
59
+ bin_dir = os.path.join(install_dir, 'dependency-check', 'bin')
60
+ if sys.platform.startswith('win'):
61
+ dc_path = os.path.join(bin_dir, 'dependency-check.bat')
62
+ else:
63
+ dc_path = os.path.join(bin_dir, 'dependency-check.sh')
64
+
65
+ # Check if dependency-check already exists
66
+ if os.path.exists(dc_path):
67
+ try:
68
+ result = subprocess.run([dc_path, '--version'], capture_output=True, text=True, timeout=10)
69
+ if result.returncode == 0:
70
+ logger.debug("dependency-check already installed and working")
71
+ # If we detected an existing root via env, retain it, else set home now.
72
+ if forced_env:
73
+ os.environ['DEPENDENCY_CHECK_HOME'] = env_home_abs
74
+ else:
75
+ os.environ['DEPENDENCY_CHECK_HOME'] = os.path.join(install_dir, 'dependency-check')
76
+ os.environ['DEPENDENCY_CHECK_VERSION'] = DEPENDENCY_CHECK_VERSION
77
+ return
78
+ except (subprocess.TimeoutExpired, FileNotFoundError) as ex:
79
+ logger.debug(f"Exception in dependency-check --version: {ex}")
80
+ pass
81
+
82
+ # Download URL
83
+ download_url = (f"https://github.com/dependency-check/DependencyCheck/releases/"
84
+ f"download/v{DEPENDENCY_CHECK_VERSION}/"
85
+ f"dependency-check-{DEPENDENCY_CHECK_VERSION}-release.zip")
86
+
87
+ os.makedirs(install_dir, exist_ok=True)
88
+ logger.info(f"Downloading dependency-check {DEPENDENCY_CHECK_VERSION} from {download_url} ...")
89
+
90
+ # Download and extract
91
+ with urllib.request.urlopen(download_url) as response:
92
+ content = response.read()
93
+
94
+ with tempfile.NamedTemporaryFile(suffix='.zip', delete=False) as tmp_file:
95
+ tmp_file.write(content)
96
+ tmp_zip_path = tmp_file.name
97
+
98
+ with zipfile.ZipFile(tmp_zip_path, 'r') as zip_ref:
99
+ zip_ref.extractall(install_dir)
100
+ os.unlink(tmp_file.name)
101
+
102
+ # Make shell scripts executable
103
+ if os.path.exists(bin_dir):
104
+ if sys.platform.startswith('win'):
105
+ # Windows: .bat files only
106
+ scripts = ["dependency-check.bat"]
107
+ else:
108
+ # Linux/macOS: .sh files only
109
+ scripts = ["dependency-check.sh", "completion-for-dependency-check.sh"]
110
+
111
+ for script in scripts:
112
+ script_path = os.path.join(bin_dir, script)
113
+ if os.path.exists(script_path):
114
+ st = os.stat(script_path)
115
+ os.chmod(script_path, st.st_mode | stat.S_IEXEC)
116
+
117
+ logger.info("✅ OWASP dependency-check installed successfully!")
118
+ logger.info(f"Installed to: {os.path.join(install_dir, 'dependency-check')}")
119
+
120
+ # Set environment variables after successful installation
121
+ os.environ['DEPENDENCY_CHECK_VERSION'] = DEPENDENCY_CHECK_VERSION
122
+ os.environ['DEPENDENCY_CHECK_HOME'] = os.path.join(install_dir, 'dependency-check')
123
+
124
+ return True
125
+
126
+ except Exception as e:
127
+ logger.error(f"Failed to install dependency-check: {e}")
128
+ logger.info("dependency-check can be installed manually from: https://github.com/dependency-check/DependencyCheck/releases")
129
+ return False
130
+
131
+
132
+ def _auto_install_dependencies():
133
+ """Auto-install required dependencies if not present."""
134
+ # Only run this once per session
135
+ if hasattr(_auto_install_dependencies, '_already_run'):
136
+ return
137
+ _auto_install_dependencies._already_run = True
138
+
139
+ try:
140
+ # Install binary version
141
+ _install_dependency_check()
142
+
143
+ logger.info(f"✅ dependency-check setup completed with version {DEPENDENCY_CHECK_VERSION}")
144
+ except Exception as e:
145
+ logger.warning(f"Auto-install failed: {e}")
146
+
147
+
148
+ # Auto-install on import
149
+ _auto_install_dependencies()
@@ -2,14 +2,18 @@
2
2
  # -*- coding: utf-8 -*-
3
3
  # Copyright (c) 2020 LG Electronics Inc.
4
4
  # SPDX-License-Identifier: Apache-2.0
5
- from fosslight_util.oss_item import FileItem
5
+ import os
6
6
  import urllib.parse
7
7
  import logging
8
8
  import fosslight_util.constant as constant
9
+ from typing import Tuple
10
+ from fosslight_util.oss_item import FileItem
9
11
 
10
12
  EXCLUDE_TRUE_VALUE = "Exclude"
11
13
  TLSH_CHECKSUM_NULL = "0"
12
14
  MAX_EXCEL_URL_LENGTH = 255
15
+ EXCEEDED_VUL_URL_LENGTH_COMMENT = f"Exceeded the maximum vulnerability URL length of {MAX_EXCEL_URL_LENGTH} characters."
16
+ _PACKAGE_DIR = ["node_modules", "venv", "Pods", "Carthage"]
13
17
 
14
18
  logger = logging.getLogger(constant.LOGGER_NAME)
15
19
 
@@ -54,12 +58,9 @@ class BinaryItem(FileItem):
54
58
  nvd_url = ", ".join(nvd_url).strip()
55
59
 
56
60
  if nvd_url and len(nvd_url) > MAX_EXCEL_URL_LENGTH:
57
- oss.comment = f"Exceeded the maximum vulnerability URL length of {MAX_EXCEL_URL_LENGTH} characters."
61
+ oss.comment = EXCEEDED_VUL_URL_LENGTH_COMMENT
58
62
  return nvd_url
59
63
 
60
- def get_print_binary_only(self):
61
- return (self.source_name_or_path + "\t" + self.checksum + "\t" + self.tlsh)
62
-
63
64
  def get_print_array(self):
64
65
  items = []
65
66
  if self.oss_items:
@@ -110,3 +111,15 @@ class BinaryItem(FileItem):
110
111
  if self.comment:
111
112
  json_item["comment"] = self.comment
112
113
  return items
114
+
115
+
116
+ def is_package_dir(bin_with_path: str, _root_path: str) -> Tuple[bool, str]:
117
+ is_pkg = False
118
+ pkg_path = ""
119
+ path_parts = bin_with_path.split(os.path.sep)
120
+ for pkg_dir in _PACKAGE_DIR:
121
+ if pkg_dir in path_parts:
122
+ pkg_index = path_parts.index(pkg_dir)
123
+ pkg_path = os.path.sep.join(path_parts[:pkg_index + 1]).replace(_root_path, '', 1)
124
+ is_pkg = True
125
+ return is_pkg, pkg_path
@@ -7,8 +7,9 @@ import tlsh
7
7
  import logging
8
8
  import psycopg2
9
9
  import pandas as pd
10
+ import socket
10
11
  from urllib.parse import urlparse
11
- from ._binary import TLSH_CHECKSUM_NULL
12
+ from fosslight_binary._binary import TLSH_CHECKSUM_NULL
12
13
  from fosslight_util.oss_item import OssItem
13
14
  import fosslight_util.constant as constant
14
15
 
@@ -18,47 +19,67 @@ columns = ['filename', 'pathname', 'checksum', 'tlshchecksum', 'ossname',
18
19
  conn = ""
19
20
  cur = ""
20
21
  logger = logging.getLogger(constant.LOGGER_NAME)
22
+ DB_URL_DEFAULT = "postgresql://bin_analysis_script_user:script_123@bat.lge.com:5432/bat"
21
23
 
22
24
 
23
25
  def get_oss_info_from_db(bin_info_list, dburl=""):
24
26
  _cnt_auto_identified = 0
25
- conn_str = get_connection_string(dburl)
26
- connect_to_lge_bin_db(conn_str)
27
-
28
- if conn != "" and cur != "":
29
- for item in bin_info_list:
30
- bin_oss_items = []
31
- tlsh_value = item.tlsh
32
- checksum_value = item.checksum
33
- bin_file_name = item.binary_name_without_path
34
-
35
- df_result = get_oss_info_by_tlsh_and_filename(
36
- bin_file_name, checksum_value, tlsh_value)
37
- if df_result is not None and len(df_result) > 0:
38
- _cnt_auto_identified += 1
39
- # Initialize the saved contents at .jar analyzing only once
40
- if not item.found_in_owasp and item.oss_items:
41
- item.oss_items = []
42
-
43
- for idx, row in df_result.iterrows():
44
- if not item.found_in_owasp:
45
- oss_from_db = OssItem(row['ossname'], row['ossversion'], row['license'])
46
-
47
- if bin_oss_items:
48
- if not any(oss_item.name == oss_from_db.name
49
- and oss_item.version == oss_from_db.version
50
- and oss_item.license == oss_from_db.license
51
- for oss_item in bin_oss_items):
27
+ conn_str, dbc = get_connection_string(dburl)
28
+ # DB URL에서 host 추출
29
+ try:
30
+ db_host = dbc.hostname
31
+ except Exception as ex:
32
+ logger.warning(f"Failed to parse DB URL for host: {ex}")
33
+ db_host = None
34
+
35
+ is_internal = False
36
+ if db_host:
37
+ try:
38
+ # DNS lookup 시도
39
+ socket.gethostbyname(db_host)
40
+ is_internal = True
41
+ except Exception:
42
+ is_internal = False
43
+
44
+ if is_internal:
45
+ connect_to_lge_bin_db(conn_str)
46
+ if conn != "" and cur != "":
47
+ for item in bin_info_list:
48
+ bin_oss_items = []
49
+ tlsh_value = item.tlsh
50
+ checksum_value = item.checksum
51
+ bin_file_name = item.binary_name_without_path
52
+
53
+ df_result = get_oss_info_by_tlsh_and_filename(
54
+ bin_file_name, checksum_value, tlsh_value)
55
+ if df_result is not None and len(df_result) > 0:
56
+ _cnt_auto_identified += 1
57
+ # Initialize the saved contents at .jar analyzing only once
58
+ if not item.found_in_owasp and item.oss_items:
59
+ item.oss_items = []
60
+
61
+ for idx, row in df_result.iterrows():
62
+ if not item.found_in_owasp:
63
+ oss_from_db = OssItem(row['ossname'], row['ossversion'], row['license'])
64
+
65
+ if bin_oss_items:
66
+ if not any(oss_item.name == oss_from_db.name
67
+ and oss_item.version == oss_from_db.version
68
+ and oss_item.license == oss_from_db.license
69
+ for oss_item in bin_oss_items):
70
+ bin_oss_items.append(oss_from_db)
71
+ else:
52
72
  bin_oss_items.append(oss_from_db)
53
- else:
54
- bin_oss_items.append(oss_from_db)
55
-
56
- if bin_oss_items:
57
- item.set_oss_items(bin_oss_items)
58
- item.comment = "Binary DB result"
59
- item.found_in_binary = True
60
73
 
61
- disconnect_lge_bin_db()
74
+ if bin_oss_items:
75
+ item.set_oss_items(bin_oss_items)
76
+ item.comment = "Binary DB result"
77
+ item.found_in_binary = True
78
+ else:
79
+ logger.warning(f"Internal network detected, but DB connection to '{db_host}' failed. Skipping DB query.")
80
+ disconnect_lge_bin_db()
81
+ else:
82
+ logger.debug(f"Binary DB host '{db_host}' is not reachable. Skipping DB query.")
62
83
  return bin_info_list, _cnt_auto_identified
63
84
 
64
85
 
@@ -66,9 +87,10 @@ def get_connection_string(dburl):
66
87
  # dburl format : 'postgresql://username:password@host:port/database_name'
67
88
  connection_string = ""
68
89
  user_dburl = True
90
+ dbc = ""
69
91
  if dburl == "" or dburl is None:
70
92
  user_dburl = False
71
- dburl = "postgresql://bin_analysis_script_user:script_123@bat.lge.com:5432/bat"
93
+ dburl = DB_URL_DEFAULT
72
94
  try:
73
95
  if user_dburl:
74
96
  logger.debug("DB URL:" + dburl)
@@ -83,7 +105,7 @@ def get_connection_string(dburl):
83
105
  if user_dburl:
84
106
  logger.warning(f"(Minor) Failed to parsing db url : {ex}")
85
107
 
86
- return connection_string
108
+ return connection_string, dbc
87
109
 
88
110
 
89
111
  def get_oss_info_by_tlsh_and_filename(file_name, checksum_value, tlsh_value):
@@ -7,23 +7,26 @@ import logging
7
7
  import json
8
8
  import os
9
9
  import sys
10
+ import subprocess
10
11
  import fosslight_util.constant as constant
11
- from ._binary import BinaryItem, VulnerabilityItem
12
+ from fosslight_binary._binary import BinaryItem, VulnerabilityItem, is_package_dir
12
13
  from fosslight_util.oss_item import OssItem
13
- from dependency_check import run as dependency_check_run
14
-
15
14
 
16
15
  logger = logging.getLogger(constant.LOGGER_NAME)
17
16
 
18
17
 
19
- def run_analysis(params, func):
18
+ def run_analysis(command):
20
19
  try:
21
- sys.argv = params
22
- func()
23
- except SystemExit:
24
- pass
20
+ result = subprocess.run(command, text=True, timeout=600)
21
+ if result.returncode != 0:
22
+ logger.error(f"dependency-check failed with return code {result.returncode}")
23
+ raise Exception(f"dependency-check failed with return code {result.returncode}")
24
+ except subprocess.TimeoutExpired:
25
+ logger.error("dependency-check command timed out")
26
+ raise
25
27
  except Exception as ex:
26
28
  logger.error(f"Run Analysis : {ex}")
29
+ raise
27
30
 
28
31
 
29
32
  def get_oss_ver(version_info):
@@ -57,29 +60,42 @@ def get_oss_lic_in_jar(data):
57
60
  return license
58
61
 
59
62
 
63
+ def merge_oss_and_vul_items(bin, key, oss_list, vulnerability_items):
64
+ bin.set_oss_items(oss_list)
65
+ if vulnerability_items and vulnerability_items.get(key):
66
+ bin.vulnerability_items.extend(vulnerability_items.get(key, []))
67
+
68
+
60
69
  def merge_binary_list(owasp_items, vulnerability_items, bin_list):
61
70
  not_found_bin = []
62
71
 
63
- # key : file_path / value : oss_list for one binary
72
+ # key : file_path / value : {"oss_list": [oss], "sha1": sha1} for one binary
64
73
  for key, value in owasp_items.items():
65
74
  found = False
75
+ oss_list = value["oss_list"]
76
+ sha1 = value.get("sha1", "")
66
77
  for bin in bin_list:
67
78
  if bin.source_name_or_path == key:
68
- for oss in value:
79
+ found = True
80
+ for oss in oss_list:
69
81
  if oss.name and oss.license:
70
82
  bin.found_in_owasp = True
71
83
  break
72
- bin.set_oss_items(value)
73
- if vulnerability_items and vulnerability_items.get(key):
74
- bin.vulnerability_items.extend(vulnerability_items.get(key))
75
- found = True
76
- break
84
+ merge_oss_and_vul_items(bin, key, oss_list, vulnerability_items)
85
+ else:
86
+ if bin.checksum == sha1:
87
+ merge_oss_and_vul_items(bin, key, oss_list, vulnerability_items)
77
88
 
78
89
  if not found:
79
90
  bin_item = BinaryItem(os.path.abspath(key))
80
91
  bin_item.binary_name_without_path = os.path.basename(key)
81
92
  bin_item.source_name_or_path = key
82
- bin_item.set_oss_items(value)
93
+
94
+ is_pkg, _ = is_package_dir(bin_item.source_name_or_path, '')
95
+ if is_pkg:
96
+ continue
97
+
98
+ bin_item.set_oss_items(oss_list)
83
99
  not_found_bin.append(bin_item)
84
100
 
85
101
  bin_list += not_found_bin
@@ -172,12 +188,27 @@ def analyze_jar_file(path_to_find_bin, path_to_exclude):
172
188
  success = True
173
189
  json_file = ""
174
190
 
175
- command = ['dependency-check', '--scan', f'{path_to_find_bin}', '--out', f'{path_to_find_bin}',
191
+ # Use fixed install path: ./fosslight_dc_bin/dependency-check/bin/dependency-check.sh or .bat
192
+ if sys.platform.startswith('win'):
193
+ depcheck_path = os.path.abspath(os.path.join(os.getcwd(), 'fosslight_dc_bin', 'dependency-check', 'bin', 'dependency-check.bat'))
194
+ elif sys.platform.startswith('linux'):
195
+ depcheck_path = os.path.abspath(os.path.join(os.getcwd(), 'fosslight_dc_bin', 'dependency-check', 'bin', 'dependency-check.sh'))
196
+ elif sys.platform.startswith('darwin'):
197
+ depcheck_path = os.path.abspath(os.path.join(os.getcwd(), 'dependency-check'))
198
+
199
+ if not (os.path.isfile(depcheck_path) and os.access(depcheck_path, os.X_OK)):
200
+ logger.error(f'dependency-check script not found or not executable at {depcheck_path}')
201
+ success = False
202
+ return owasp_items, vulnerability_items, success
203
+
204
+ command = [depcheck_path, '--scan', f'{path_to_find_bin}', '--out', f'{path_to_find_bin}',
176
205
  '--disableArchive', '--disableAssembly', '--disableRetireJS', '--disableNodeJS',
177
206
  '--disableNodeAudit', '--disableNugetconf', '--disableNuspec', '--disableOpenSSL',
178
- '--disableOssIndex', '--disableBundleAudit', '--cveValidForHours', '24', '-f', 'JSON']
207
+ '--disableOssIndex', '--disableBundleAudit', '--disableOssIndex', '--nvdValidForHours', '168',
208
+ '--nvdDatafeed', 'https://nvd.nist.gov/feeds/json/cve/2.0/nvdcve-2.0-{0}.json.gz', '-f', 'JSON']
209
+
179
210
  try:
180
- run_analysis(command, dependency_check_run)
211
+ run_analysis(command)
181
212
  except Exception as ex:
182
213
  logger.info(f"Error to analyze .jar file - OSS information for .jar file isn't included in report.\n {ex}")
183
214
  success = False
@@ -192,7 +223,8 @@ def analyze_jar_file(path_to_find_bin, path_to_exclude):
192
223
  success = False
193
224
  return owasp_items, vulnerability_items, success
194
225
 
195
- dependencies = jar_contents.get("dependencies")
226
+ dependencies = jar_contents.get("dependencies", [])
227
+
196
228
  try:
197
229
  for val in dependencies:
198
230
  bin_with_path = ""
@@ -204,6 +236,8 @@ def analyze_jar_file(path_to_find_bin, path_to_exclude):
204
236
  oss_license = get_oss_lic_in_jar(val)
205
237
  oss_name_found = False
206
238
 
239
+ sha1 = val.get("sha1", "")
240
+
207
241
  all_evidence = val.get("evidenceCollected", {})
208
242
  vulnerability = val.get("vulnerabilityIds", [])
209
243
  all_pkg_info = val.get("packages", [])
@@ -223,7 +257,22 @@ def analyze_jar_file(path_to_find_bin, path_to_exclude):
223
257
  if not bin_with_path.endswith('.jar'):
224
258
  bin_with_path = bin_with_path.split('.jar')[0] + '.jar'
225
259
 
226
- file_with_path = os.path.relpath(bin_with_path, path_to_find_bin)
260
+ try:
261
+ path_to_fild_bin_abs = os.path.abspath(path_to_find_bin)
262
+ bin_with_path_abs = os.path.abspath(bin_with_path)
263
+ if os.name == 'nt': # Windows
264
+ drive_bin = os.path.splitdrive(bin_with_path_abs)[0].lower()
265
+ drive_root = os.path.splitdrive(path_to_fild_bin_abs)[0].lower()
266
+ # Different drive or UNC root -> fallback to basename
267
+ if drive_bin and drive_root and drive_bin != drive_root:
268
+ file_with_path = os.path.basename(bin_with_path_abs)
269
+ else:
270
+ file_with_path = os.path.relpath(bin_with_path_abs, path_to_fild_bin_abs)
271
+ else:
272
+ file_with_path = os.path.relpath(bin_with_path_abs, path_to_fild_bin_abs)
273
+ except Exception as e:
274
+ file_with_path = os.path.basename(bin_with_path)
275
+ logger.error(f"relpath error: {e}; fallback basename: {file_with_path}")
227
276
 
228
277
  # First, Get OSS Name and Version info from pkg_info
229
278
  for pkg_info in all_pkg_info:
@@ -259,31 +308,26 @@ def analyze_jar_file(path_to_find_bin, path_to_exclude):
259
308
  # Get Vulnerability Info.
260
309
  vulnerability_items = get_vulnerability_info(file_with_path, vulnerability, vulnerability_items, remove_vulnerability_items)
261
310
 
262
- if oss_name != "" or oss_ver != "" or oss_license != "" or oss_dl_url != "":
263
- oss_list_for_file = owasp_items.get(file_with_path, [])
264
-
265
- existing_oss = None
266
- for item in oss_list_for_file:
267
- if item.name == oss_name and item.version == oss_ver:
268
- existing_oss = item
269
- break
270
-
271
- if not existing_oss:
272
- oss = OssItem(oss_name, oss_ver, oss_license, oss_dl_url)
273
- oss.comment = "OWASP result"
311
+ if oss_name or oss_license or oss_dl_url:
312
+ oss = OssItem(oss_name, oss_ver, oss_license, oss_dl_url)
313
+ oss.comment = "OWASP result"
274
314
 
275
- if file_with_path in owasp_items:
276
- owasp_items[file_with_path].append(oss)
277
- else:
278
- owasp_items[file_with_path] = [oss]
315
+ if file_with_path in owasp_items:
316
+ owasp_items[file_with_path]["oss_list"].append(oss)
317
+ # Update sha1 if not already set or if current sha1 is empty
318
+ if not owasp_items[file_with_path]["sha1"] and sha1:
319
+ owasp_items[file_with_path]["sha1"] = sha1
320
+ else:
321
+ owasp_items[file_with_path] = {
322
+ "oss_list": [oss],
323
+ "sha1": sha1
324
+ }
279
325
  except Exception as ex:
280
- logger.debug(f"Error to get depency Info in jar_contets: {ex}")
281
- success = False
326
+ logger.debug(f"Error to get dependency Info in jar_contents: {ex}")
282
327
 
283
328
  try:
284
329
  if os.path.isfile(json_file):
285
330
  os.remove(json_file)
286
331
  except Exception as ex:
287
332
  logger.debug(f"Error - There is no .json file : {ex}")
288
-
289
333
  return owasp_items, vulnerability_items, success
@@ -16,7 +16,7 @@ from fosslight_util.set_log import init_log
16
16
  import fosslight_util.constant as constant
17
17
  from fosslight_util.output_format import check_output_formats_v2, write_output_file
18
18
  from ._binary_dao import get_oss_info_from_db
19
- from ._binary import BinaryItem, TLSH_CHECKSUM_NULL
19
+ from ._binary import BinaryItem, TLSH_CHECKSUM_NULL, is_package_dir
20
20
  from ._jar_analysis import analyze_jar_file, merge_binary_list
21
21
  from ._simple_mode import print_simple_mode, filter_binary, init_simple
22
22
  from fosslight_util.correct import correct_with_yaml
@@ -165,8 +165,15 @@ def get_file_list(path_to_find, abs_path_to_exclude):
165
165
  bin_with_path = os.path.join(root, file)
166
166
  bin_item = BinaryItem(bin_with_path)
167
167
  bin_item.binary_name_without_path = file
168
- bin_item.source_name_or_path = bin_with_path.replace(
169
- _root_path, '', 1)
168
+ bin_item.source_name_or_path = bin_with_path.replace(_root_path, '', 1)
169
+
170
+ is_pkg, pkg_path = is_package_dir(bin_with_path, _root_path)
171
+ if is_pkg:
172
+ bin_item.source_name_or_path = pkg_path
173
+ if not any(x.source_name_or_path == bin_item.source_name_or_path for x in bin_list):
174
+ bin_item.exclude = True
175
+ bin_list.append(bin_item)
176
+ continue
170
177
 
171
178
  if any(dir_name in dir_path for dir_name in _EXCLUDE_DIR):
172
179
  bin_item.exclude = True
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fosslight_binary
3
- Version: 5.1.8
3
+ Version: 5.1.10
4
4
  Summary: FOSSLight Binary Scanner
5
5
  Home-page: https://github.com/fosslight/fosslight_binary_scanner
6
6
  Download-URL: https://github.com/fosslight/fosslight_binary_scanner
@@ -27,7 +27,6 @@ Requires-Dist: pytz
27
27
  Requires-Dist: XlsxWriter
28
28
  Requires-Dist: PyYAML
29
29
  Requires-Dist: fosslight_util>=2.1.13
30
- Requires-Dist: dependency-check
31
30
  Requires-Dist: python-magic-bin; sys_platform == "win32"
32
31
  Requires-Dist: python-magic; "darwin" in sys_platform
33
32
  Requires-Dist: python-magic; "linux" in sys_platform
@@ -9,7 +9,6 @@ pytz
9
9
  XlsxWriter
10
10
  PyYAML
11
11
  fosslight_util>=2.1.13
12
- dependency-check
13
12
 
14
13
  [:"darwin" in sys_platform]
15
14
  python-magic
File without changes