Skip to content

Commit b04025e

Browse files
committed
add flag --reach-use-only-pregenerated-sboms to exclude non-CDX and SPDX files from a Tier 1 reachability scan
1 parent d06deb0 commit b04025e

File tree

5 files changed

+98
-7
lines changed

5 files changed

+98
-7
lines changed

socketsecurity/config.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ class CliConfig:
7777
reach_concurrency: Optional[int] = None
7878
reach_additional_params: Optional[List[str]] = None
7979
only_facts_file: bool = False
80+
reach_only_use_pre_generated_sboms: bool = False
8081

8182
@classmethod
8283
def from_args(cls, args_list: Optional[List[str]] = None) -> 'CliConfig':
@@ -139,6 +140,7 @@ def from_args(cls, args_list: Optional[List[str]] = None) -> 'CliConfig':
139140
'reach_concurrency': args.reach_concurrency,
140141
'reach_additional_params': args.reach_additional_params,
141142
'only_facts_file': args.only_facts_file,
143+
'reach_only_use_pre_generated_sboms': args.reach_only_use_pre_generated_sboms,
142144
'version': __version__
143145
}
144146
try:
@@ -175,6 +177,11 @@ def from_args(cls, args_list: Optional[List[str]] = None) -> 'CliConfig':
175177
logging.error("--only-facts-file requires --reach to be specified")
176178
exit(1)
177179

180+
# Validate that reach_only_use_pre_generated_sboms requires reach
181+
if args.reach_only_use_pre_generated_sboms and not args.reach:
182+
logging.error("--reach-only-use-pre-generated-sboms requires --reach to be specified")
183+
exit(1)
184+
178185
# Validate reach_concurrency is >= 1 if provided
179186
if args.reach_concurrency is not None and args.reach_concurrency < 1:
180187
logging.error("--reach-concurrency must be >= 1")
@@ -602,6 +609,12 @@ def create_argument_parser() -> argparse.ArgumentParser:
602609
action="store_true",
603610
help="Submit only the .socket.facts.json file when creating full scan (requires --reach)"
604611
)
612+
reachability_group.add_argument(
613+
"--reach-only-use-pre-generated-sboms",
614+
dest="reach_only_use_pre_generated_sboms",
615+
action="store_true",
616+
help="When using this option, the scan is created based only on pre-generated CDX and SPDX files in your project. (requires --reach)"
617+
)
605618

606619
parser.add_argument(
607620
'--version',

socketsecurity/core/__init__.py

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -343,6 +343,57 @@ def find_files(self, path: str) -> List[str]:
343343

344344
return file_list
345345

346+
def find_sbom_files(self, path: str) -> List[str]:
347+
"""
348+
Finds only pre-generated SBOM files (CDX and SPDX) in the given path.
349+
350+
This is used with --reach-only-use-pre-generated-sboms to find only
351+
pre-computed CycloneDX and SPDX manifest files.
352+
353+
Args:
354+
path: Path to search for SBOM files.
355+
356+
Returns:
357+
List of found CDX and SPDX file paths.
358+
"""
359+
log.debug("Starting Find SBOM Files (CDX and SPDX only)")
360+
files: Set[str] = set()
361+
362+
# Get supported patterns from the API and filter to only cdx and spdx
363+
all_patterns = self.get_supported_patterns()
364+
sbom_ecosystems = ['cdx', 'spdx']
365+
sbom_patterns = {k: v for k, v in all_patterns.items() if k in sbom_ecosystems}
366+
367+
if not sbom_patterns:
368+
log.warning("No CDX or SPDX patterns found in supported patterns from API")
369+
return []
370+
371+
for ecosystem in sbom_patterns:
372+
log.debug(f'Scanning for {ecosystem} files')
373+
ecosystem_patterns = sbom_patterns[ecosystem]
374+
for file_name in ecosystem_patterns:
375+
original_pattern = ecosystem_patterns[file_name]["pattern"]
376+
377+
# Expand brace patterns
378+
expanded_patterns = Core.expand_brace_pattern(original_pattern)
379+
380+
for pattern in expanded_patterns:
381+
case_insensitive_pattern = Core.to_case_insensitive_regex(pattern)
382+
file_path = os.path.join(path, "**", case_insensitive_pattern)
383+
384+
log.debug(f"Globbing {file_path}")
385+
glob_files = glob(file_path, recursive=True)
386+
387+
for glob_file in glob_files:
388+
if os.path.isfile(glob_file) and not Core.is_excluded(glob_file, self.config.excluded_dirs):
389+
files.add(glob_file.replace("\\", "/"))
390+
391+
file_list = sorted(files)
392+
file_count = len(file_list)
393+
log.info(f"Total SBOM files found (CDX/SPDX): {file_count}")
394+
395+
return file_list
396+
346397
def get_supported_patterns(self) -> Dict:
347398
"""
348399
Gets supported file patterns from the Socket API.

socketsecurity/core/tools/reachability.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -101,10 +101,11 @@ def run_reachability_analysis(
101101
additional_params: Optional[List[str]] = None,
102102
allow_unverified: bool = False,
103103
enable_debug: bool = False,
104+
use_only_pregenerated_sboms: bool = False,
104105
) -> Dict[str, Any]:
105106
"""
106107
Run reachability analysis.
107-
108+
108109
Args:
109110
org_slug: Socket organization slug
110111
target_directory: Directory to analyze
@@ -125,7 +126,8 @@ def run_reachability_analysis(
125126
additional_params: Additional parameters to pass to coana CLI
126127
allow_unverified: Disable SSL certificate verification (sets NODE_TLS_REJECT_UNAUTHORIZED=0)
127128
enable_debug: Enable debug mode (passes -d flag to coana CLI)
128-
129+
use_only_pregenerated_sboms: Use only pre-generated CDX and SPDX files for the scan
130+
129131
Returns:
130132
Dict containing scan_id and report_path
131133
"""
@@ -179,7 +181,10 @@ def run_reachability_analysis(
179181

180182
if enable_debug:
181183
cmd.append("-d")
182-
184+
185+
if use_only_pregenerated_sboms:
186+
cmd.append("--use-only-pregenerated-sboms")
187+
183188
# Add any additional parameters provided by the user
184189
if additional_params:
185190
cmd.extend(additional_params)

socketsecurity/socketcli.py

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,8 @@ def main_code():
167167

168168
# Variable to track if we need to override files with facts file
169169
facts_file_to_submit = None
170+
# Variable to track SBOM files to submit when using --reach-only-use-pre-generated-sboms
171+
sbom_files_to_submit = None
170172

171173
# Git setup
172174
is_repo = False
@@ -230,12 +232,14 @@ def main_code():
230232
# Run reachability analysis if enabled
231233
if config.reach:
232234
from socketsecurity.core.tools.reachability import ReachabilityAnalyzer
233-
235+
234236
log.info("Starting reachability analysis...")
235-
237+
236238
# Find manifest files in scan paths (excluding .socket.facts.json to avoid circular dependency)
237239
log.info("Finding manifest files for reachability analysis...")
238240
manifest_files = []
241+
242+
# Always find all manifest files for the tar hash upload
239243
for scan_path in scan_paths:
240244
scan_manifests = core.find_files(scan_path)
241245
# Filter out .socket.facts.json files from manifest upload
@@ -289,7 +293,8 @@ def main_code():
289293
concurrency=config.reach_concurrency,
290294
additional_params=config.reach_additional_params,
291295
allow_unverified=config.allow_unverified,
292-
enable_debug=config.enable_debug
296+
enable_debug=config.enable_debug,
297+
use_only_pregenerated_sboms=config.reach_only_use_pre_generated_sboms
293298
)
294299

295300
log.info(f"Reachability analysis completed successfully")
@@ -301,6 +306,17 @@ def main_code():
301306
if config.only_facts_file:
302307
facts_file_to_submit = os.path.abspath(output_path)
303308
log.info(f"Only-facts-file mode: will submit only {facts_file_to_submit}")
309+
310+
# If reach-only-use-pre-generated-sboms mode, submit CDX, SPDX, and facts file
311+
if config.reach_only_use_pre_generated_sboms:
312+
# Find only CDX and SPDX files for the final scan submission
313+
sbom_files_to_submit = []
314+
for scan_path in scan_paths:
315+
sbom_files_to_submit.extend(core.find_sbom_files(scan_path))
316+
facts_path = os.path.abspath(output_path)
317+
if os.path.exists(facts_path):
318+
sbom_files_to_submit.append(facts_path)
319+
log.info(f"Pre-generated SBOMs mode: will submit {len(sbom_files_to_submit)} files (CDX, SPDX, and facts file)")
304320

305321
except Exception as e:
306322
log.error(f"Reachability analysis failed: {str(e)}")
@@ -331,6 +347,12 @@ def main_code():
331347
files_explicitly_specified = True
332348
log.debug(f"Overriding files to only submit facts file: {facts_file_to_submit}")
333349

350+
# Override files if reach-only-use-pre-generated-sboms mode is active
351+
if sbom_files_to_submit:
352+
specified_files = sbom_files_to_submit
353+
files_explicitly_specified = True
354+
log.debug(f"Overriding files to submit only SBOM files (CDX, SPDX, and facts): {sbom_files_to_submit}")
355+
334356
# Determine files to check based on the new logic
335357
files_to_check = []
336358
force_api_mode = False

uv.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)