fosslight-binary 5.1.9__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.9 → fosslight_binary-5.1.10}/PKG-INFO +1 -2
  2. {fosslight_binary-5.1.9 → fosslight_binary-5.1.10}/requirements.txt +0 -1
  3. {fosslight_binary-5.1.9 → 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.9 → fosslight_binary-5.1.10}/src/fosslight_binary/_binary_dao.py +60 -38
  6. {fosslight_binary-5.1.9 → fosslight_binary-5.1.10}/src/fosslight_binary/_jar_analysis.py +45 -12
  7. {fosslight_binary-5.1.9 → fosslight_binary-5.1.10}/src/fosslight_binary.egg-info/PKG-INFO +1 -2
  8. {fosslight_binary-5.1.9 → fosslight_binary-5.1.10}/src/fosslight_binary.egg-info/requires.txt +0 -1
  9. fosslight_binary-5.1.9/src/fosslight_binary/__init__.py +0 -0
  10. {fosslight_binary-5.1.9 → fosslight_binary-5.1.10}/LICENSE +0 -0
  11. {fosslight_binary-5.1.9 → fosslight_binary-5.1.10}/LICENSES/Apache-2.0.txt +0 -0
  12. {fosslight_binary-5.1.9 → fosslight_binary-5.1.10}/LICENSES/LicenseRef-3rd_party_licenses.txt +0 -0
  13. {fosslight_binary-5.1.9 → fosslight_binary-5.1.10}/MANIFEST.in +0 -0
  14. {fosslight_binary-5.1.9 → fosslight_binary-5.1.10}/README.md +0 -0
  15. {fosslight_binary-5.1.9 → fosslight_binary-5.1.10}/setup.cfg +0 -0
  16. {fosslight_binary-5.1.9 → fosslight_binary-5.1.10}/src/fosslight_binary/LICENSES/LICENSE +0 -0
  17. {fosslight_binary-5.1.9 → fosslight_binary-5.1.10}/src/fosslight_binary/LICENSES/LicenseRef-3rd_party_licenses.txt +0 -0
  18. {fosslight_binary-5.1.9 → fosslight_binary-5.1.10}/src/fosslight_binary/_binary.py +0 -0
  19. {fosslight_binary-5.1.9 → fosslight_binary-5.1.10}/src/fosslight_binary/_help.py +0 -0
  20. {fosslight_binary-5.1.9 → fosslight_binary-5.1.10}/src/fosslight_binary/_simple_mode.py +0 -0
  21. {fosslight_binary-5.1.9 → fosslight_binary-5.1.10}/src/fosslight_binary/binary_analysis.py +0 -0
  22. {fosslight_binary-5.1.9 → fosslight_binary-5.1.10}/src/fosslight_binary/cli.py +0 -0
  23. {fosslight_binary-5.1.9 → fosslight_binary-5.1.10}/src/fosslight_binary.egg-info/SOURCES.txt +0 -0
  24. {fosslight_binary-5.1.9 → fosslight_binary-5.1.10}/src/fosslight_binary.egg-info/dependency_links.txt +0 -0
  25. {fosslight_binary-5.1.9 → fosslight_binary-5.1.10}/src/fosslight_binary.egg-info/entry_points.txt +0 -0
  26. {fosslight_binary-5.1.9 → fosslight_binary-5.1.10}/src/fosslight_binary.egg-info/top_level.txt +0 -0
  27. {fosslight_binary-5.1.9 → 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.9
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.9',
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()
@@ -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, is_package_dir
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):
@@ -185,12 +188,27 @@ def analyze_jar_file(path_to_find_bin, path_to_exclude):
185
188
  success = True
186
189
  json_file = ""
187
190
 
188
- 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}',
189
205
  '--disableArchive', '--disableAssembly', '--disableRetireJS', '--disableNodeJS',
190
206
  '--disableNodeAudit', '--disableNugetconf', '--disableNuspec', '--disableOpenSSL',
191
- '--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
+
192
210
  try:
193
- run_analysis(command, dependency_check_run)
211
+ run_analysis(command)
194
212
  except Exception as ex:
195
213
  logger.info(f"Error to analyze .jar file - OSS information for .jar file isn't included in report.\n {ex}")
196
214
  success = False
@@ -239,7 +257,22 @@ def analyze_jar_file(path_to_find_bin, path_to_exclude):
239
257
  if not bin_with_path.endswith('.jar'):
240
258
  bin_with_path = bin_with_path.split('.jar')[0] + '.jar'
241
259
 
242
- 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}")
243
276
 
244
277
  # First, Get OSS Name and Version info from pkg_info
245
278
  for pkg_info in all_pkg_info:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fosslight_binary
3
- Version: 5.1.9
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