From c68dbccd5710b37be0135f6ecf0f16dfaa355b20 Mon Sep 17 00:00:00 2001 From: Douglas Coburn Date: Tue, 18 Mar 2025 16:43:40 -0700 Subject: [PATCH 1/3] Fix for converting supported files patterns to proper globs --- socketsecurity/config.py | 2 +- socketsecurity/core/__init__.py | 85 ++++++++++++++++++++++----------- 2 files changed, 59 insertions(+), 28 deletions(-) diff --git a/socketsecurity/config.py b/socketsecurity/config.py index 24a9eca..f46a6aa 100644 --- a/socketsecurity/config.py +++ b/socketsecurity/config.py @@ -55,7 +55,7 @@ def from_args(cls, args_list: Optional[List[str]] = None) -> 'CliConfig': 'pr_number': args.pr_number, 'commit_message': commit_message, 'default_branch': args.default_branch, - 'target_path': args.target_path, + 'target_path': os.path.expanduser(args.target_path), 'scm': args.scm, 'sbom_file': args.sbom_file, 'commit_sha': args.commit_sha, diff --git a/socketsecurity/core/__init__.py b/socketsecurity/core/__init__.py index 3d3a555..d00575f 100644 --- a/socketsecurity/core/__init__.py +++ b/socketsecurity/core/__init__.py @@ -5,8 +5,8 @@ from dataclasses import asdict from glob import glob from pathlib import PurePath -from typing import BinaryIO, Dict, List, Tuple - +from typing import BinaryIO, Dict, List, Tuple, Set +import re from socketdev import socketdev from socketdev.exceptions import APIFailure from socketdev.fullscans import FullScanParams, SocketArtifact @@ -123,19 +123,50 @@ def create_sbom_output(self, diff: Diff) -> dict: log.error(result.get("message", "No error message provided")) return {} + @staticmethod + def to_case_insensitive_regex(pattern: str) -> str: + """ + Converts a pattern to a case-insensitive regex (optional step). + If `pattern` is a glob pattern, this step should be removed. + """ + return pattern # Remove if unnecessary + + @staticmethod + def expand_brace_pattern(pattern: str) -> List[str]: + """ + Expands brace expressions (e.g., {a,b,c}) into separate patterns. + """ + brace_regex = re.compile(r"\{([^{}]+)\}") + + # Expand all brace groups + expanded_patterns = [pattern] + while any("{" in p for p in expanded_patterns): + new_patterns = [] + for pat in expanded_patterns: + match = brace_regex.search(pat) + if match: + options = match.group(1).split(",") # Extract values inside {} + prefix, suffix = pat[:match.start()], pat[match.end():] + new_patterns.extend([prefix + opt + suffix for opt in options]) + else: + new_patterns.append(pat) + expanded_patterns = new_patterns + + return expanded_patterns + def find_files(self, path: str) -> List[str]: """ Finds supported manifest files in the given path. Args: - path: Path to search for manifest files + path: Path to search for manifest files. Returns: - List of found manifest file paths + List of found manifest file paths. """ log.debug("Starting Find Files") start_time = time.time() - files = set() + files: Set[str] = set() # Get supported patterns from the API try: @@ -149,28 +180,28 @@ def find_files(self, path: str) -> List[str]: for ecosystem in patterns: ecosystem_patterns = patterns[ecosystem] for file_name in ecosystem_patterns: - pattern = Core.to_case_insensitive_regex(ecosystem_patterns[file_name]["pattern"]) - file_path = f"{path}/**/{pattern}" - #log.debug(f"Globbing {file_path}") - glob_start = time.time() - glob_files = glob(file_path, recursive=True) - for glob_file in glob_files: - # Only add if it's a file, not a directory - if glob_file not in files and os.path.isfile(glob_file): - files.add(glob_file) - glob_end = time.time() - glob_total_time = glob_end - glob_start - #log.debug(f"Glob for pattern {file_path} took {glob_total_time:.2f} seconds") - - log.debug("Finished Find Files") - end_time = time.time() - total_time = end_time - start_time - files_list = list(files) - if len(files_list) > 5: - log.debug(f"{len(files_list)} Files found ({total_time:.2f}s): {', '.join(files_list[:5])}, ...") - else: - log.debug(f"{len(files_list)} Files found ({total_time:.2f}s): {', '.join(files_list)}") - return list(files) + original_pattern = ecosystem_patterns[file_name]["pattern"] + + # Expand brace patterns + expanded_patterns = Core.expand_brace_pattern(original_pattern) + + for pattern in expanded_patterns: + case_insensitive_pattern = Core.to_case_insensitive_regex(pattern) + file_path = os.path.join(path, "**", case_insensitive_pattern) + + log.debug(f"Globbing {file_path}") + glob_start = time.time() + glob_files = glob(file_path, recursive=True) + + for glob_file in glob_files: + if os.path.isfile(glob_file): + files.add(glob_file) + + glob_end = time.time() + log.debug(f"Globbing took {glob_end - glob_start:.4f} seconds") + + log.debug(f"Total files found: {len(files)}") + return sorted(files) def get_supported_patterns(self) -> Dict: """ From 3604e094c04cae970fd07ce34b4e23ec8ee21d81 Mon Sep 17 00:00:00 2001 From: Douglas Coburn Date: Tue, 18 Mar 2025 16:44:03 -0700 Subject: [PATCH 2/3] Version bump for deploy --- socketsecurity/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/socketsecurity/__init__.py b/socketsecurity/__init__.py index ebdf23a..b8c6665 100644 --- a/socketsecurity/__init__.py +++ b/socketsecurity/__init__.py @@ -1,2 +1,2 @@ __author__ = 'socket.dev' -__version__ = '2.0.13' +__version__ = '2.0.14' From dfceec13ddf56db8799768c2a5958ad31f2e41a3 Mon Sep 17 00:00:00 2001 From: Douglas Coburn Date: Tue, 18 Mar 2025 16:50:25 -0700 Subject: [PATCH 3/3] Removed duplicate function --- socketsecurity/core/__init__.py | 8 -------- 1 file changed, 8 deletions(-) diff --git a/socketsecurity/core/__init__.py b/socketsecurity/core/__init__.py index d00575f..7fc4c80 100644 --- a/socketsecurity/core/__init__.py +++ b/socketsecurity/core/__init__.py @@ -123,14 +123,6 @@ def create_sbom_output(self, diff: Diff) -> dict: log.error(result.get("message", "No error message provided")) return {} - @staticmethod - def to_case_insensitive_regex(pattern: str) -> str: - """ - Converts a pattern to a case-insensitive regex (optional step). - If `pattern` is a glob pattern, this step should be removed. - """ - return pattern # Remove if unnecessary - @staticmethod def expand_brace_pattern(pattern: str) -> List[str]: """